111102SGavin.Maltby@Sun.COM /*
211102SGavin.Maltby@Sun.COM * CDDL HEADER START
311102SGavin.Maltby@Sun.COM *
411102SGavin.Maltby@Sun.COM * The contents of this file are subject to the terms of the
511102SGavin.Maltby@Sun.COM * Common Development and Distribution License (the "License").
611102SGavin.Maltby@Sun.COM * You may not use this file except in compliance with the License.
711102SGavin.Maltby@Sun.COM *
811102SGavin.Maltby@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911102SGavin.Maltby@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011102SGavin.Maltby@Sun.COM * See the License for the specific language governing permissions
1111102SGavin.Maltby@Sun.COM * and limitations under the License.
1211102SGavin.Maltby@Sun.COM *
1311102SGavin.Maltby@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411102SGavin.Maltby@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511102SGavin.Maltby@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611102SGavin.Maltby@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711102SGavin.Maltby@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811102SGavin.Maltby@Sun.COM *
1911102SGavin.Maltby@Sun.COM * CDDL HEADER END
2011102SGavin.Maltby@Sun.COM */
2111102SGavin.Maltby@Sun.COM
2211102SGavin.Maltby@Sun.COM /*
23*12967Sgavin.maltby@oracle.com * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2411102SGavin.Maltby@Sun.COM */
2511102SGavin.Maltby@Sun.COM
2611102SGavin.Maltby@Sun.COM /*
2711102SGavin.Maltby@Sun.COM * Subscription event access interfaces.
2811102SGavin.Maltby@Sun.COM */
2911102SGavin.Maltby@Sun.COM
3011102SGavin.Maltby@Sun.COM #include <sys/types.h>
3111102SGavin.Maltby@Sun.COM #include <limits.h>
3211102SGavin.Maltby@Sun.COM #include <atomic.h>
3311102SGavin.Maltby@Sun.COM #include <libsysevent.h>
3411102SGavin.Maltby@Sun.COM #include <umem.h>
3511102SGavin.Maltby@Sun.COM #include <fm/libfmevent.h>
3611102SGavin.Maltby@Sun.COM #include <sys/fm/protocol.h>
3711102SGavin.Maltby@Sun.COM
3811102SGavin.Maltby@Sun.COM #include "fmev_impl.h"
3911102SGavin.Maltby@Sun.COM
40*12967Sgavin.maltby@oracle.com #define FMEV_API_ENTER(iep, v) \
41*12967Sgavin.maltby@oracle.com fmev_api_enter(fmev_shdl_cmn(((iep)->ei_hdl)), LIBFMEVENT_VERSION_##v)
4211102SGavin.Maltby@Sun.COM
4311102SGavin.Maltby@Sun.COM typedef struct {
4411102SGavin.Maltby@Sun.COM uint32_t ei_magic; /* _FMEVMAGIC */
4511102SGavin.Maltby@Sun.COM volatile uint32_t ei_refcnt; /* reference count */
4611102SGavin.Maltby@Sun.COM fmev_shdl_t ei_hdl; /* handle received on */
4711102SGavin.Maltby@Sun.COM nvlist_t *ei_nvl; /* (duped) sysevent attribute list */
4811102SGavin.Maltby@Sun.COM uint64_t ei_fmtime[2]; /* embedded protocol event time */
4911102SGavin.Maltby@Sun.COM } fmev_impl_t;
5011102SGavin.Maltby@Sun.COM
5111102SGavin.Maltby@Sun.COM #define FMEV2IMPL(ev) ((fmev_impl_t *)(ev))
5211102SGavin.Maltby@Sun.COM #define IMPL2FMEV(iep) ((fmev_t)(iep))
5311102SGavin.Maltby@Sun.COM
5411102SGavin.Maltby@Sun.COM #define _FMEVMAGIC 0x466d4576 /* "FmEv" */
5511102SGavin.Maltby@Sun.COM
5611102SGavin.Maltby@Sun.COM #define EVENT_VALID(iep) ((iep)->ei_magic == _FMEVMAGIC && \
5711102SGavin.Maltby@Sun.COM (iep)->ei_refcnt > 0 && fmev_shdl_valid((iep)->ei_hdl))
5811102SGavin.Maltby@Sun.COM
5911102SGavin.Maltby@Sun.COM #define FM_TIME_SEC 0
6011102SGavin.Maltby@Sun.COM #define FM_TIME_NSEC 1
6111102SGavin.Maltby@Sun.COM
6211102SGavin.Maltby@Sun.COM /*
6311102SGavin.Maltby@Sun.COM * Transform a received sysevent_t into an fmev_t.
6411102SGavin.Maltby@Sun.COM */
6511102SGavin.Maltby@Sun.COM
6611102SGavin.Maltby@Sun.COM uint64_t fmev_bad_attr, fmev_bad_tod, fmev_bad_class;
6711102SGavin.Maltby@Sun.COM
6811102SGavin.Maltby@Sun.COM fmev_t
fmev_sysev2fmev(fmev_shdl_t hdl,sysevent_t * sep,char ** clsp,nvlist_t ** nvlp)6911102SGavin.Maltby@Sun.COM fmev_sysev2fmev(fmev_shdl_t hdl, sysevent_t *sep, char **clsp, nvlist_t **nvlp)
7011102SGavin.Maltby@Sun.COM {
7111102SGavin.Maltby@Sun.COM fmev_impl_t *iep;
7211102SGavin.Maltby@Sun.COM uint64_t *tod;
7311102SGavin.Maltby@Sun.COM uint_t nelem;
7411102SGavin.Maltby@Sun.COM
7511102SGavin.Maltby@Sun.COM if ((iep = fmev_shdl_alloc(hdl, sizeof (*iep))) == NULL)
7611102SGavin.Maltby@Sun.COM return (NULL);
7711102SGavin.Maltby@Sun.COM
7811102SGavin.Maltby@Sun.COM /*
7911102SGavin.Maltby@Sun.COM * sysevent_get_attr_list duplicates the nvlist - we free it
8011102SGavin.Maltby@Sun.COM * in fmev_free when the reference count hits zero.
8111102SGavin.Maltby@Sun.COM */
8211102SGavin.Maltby@Sun.COM if (sysevent_get_attr_list(sep, &iep->ei_nvl) != 0) {
8311102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, iep, sizeof (*iep));
8411102SGavin.Maltby@Sun.COM fmev_bad_attr++;
8511102SGavin.Maltby@Sun.COM return (NULL);
8611102SGavin.Maltby@Sun.COM }
8711102SGavin.Maltby@Sun.COM
8811102SGavin.Maltby@Sun.COM *nvlp = iep->ei_nvl;
8911102SGavin.Maltby@Sun.COM
9011102SGavin.Maltby@Sun.COM if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, clsp) != 0) {
9111102SGavin.Maltby@Sun.COM nvlist_free(iep->ei_nvl);
9211102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, iep, sizeof (*iep));
9311102SGavin.Maltby@Sun.COM fmev_bad_class++;
9411102SGavin.Maltby@Sun.COM return (NULL);
9511102SGavin.Maltby@Sun.COM }
9611102SGavin.Maltby@Sun.COM
9711102SGavin.Maltby@Sun.COM if (nvlist_lookup_uint64_array(iep->ei_nvl, "__tod", &tod,
9811102SGavin.Maltby@Sun.COM &nelem) != 0 || nelem != 2) {
9911102SGavin.Maltby@Sun.COM nvlist_free(iep->ei_nvl);
10011102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, iep, sizeof (*iep));
10111102SGavin.Maltby@Sun.COM fmev_bad_tod++;
10211102SGavin.Maltby@Sun.COM return (NULL);
10311102SGavin.Maltby@Sun.COM }
10411102SGavin.Maltby@Sun.COM
10511102SGavin.Maltby@Sun.COM iep->ei_fmtime[FM_TIME_SEC] = tod[0];
10611102SGavin.Maltby@Sun.COM iep->ei_fmtime[FM_TIME_NSEC] = tod[1];
10711102SGavin.Maltby@Sun.COM
10811102SGavin.Maltby@Sun.COM /*
10911102SGavin.Maltby@Sun.COM * Now remove the fmd-private __tod and __ttl members.
11011102SGavin.Maltby@Sun.COM */
11111102SGavin.Maltby@Sun.COM (void) nvlist_remove_all(iep->ei_nvl, "__tod");
11211102SGavin.Maltby@Sun.COM (void) nvlist_remove_all(iep->ei_nvl, "__ttl");
11311102SGavin.Maltby@Sun.COM
11411102SGavin.Maltby@Sun.COM iep->ei_magic = _FMEVMAGIC;
11511102SGavin.Maltby@Sun.COM iep->ei_hdl = hdl;
11611102SGavin.Maltby@Sun.COM iep->ei_refcnt = 1;
11711102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
11811102SGavin.Maltby@Sun.COM
11911102SGavin.Maltby@Sun.COM return (IMPL2FMEV(iep));
12011102SGavin.Maltby@Sun.COM }
12111102SGavin.Maltby@Sun.COM
12211102SGavin.Maltby@Sun.COM static void
fmev_free(fmev_impl_t * iep)12311102SGavin.Maltby@Sun.COM fmev_free(fmev_impl_t *iep)
12411102SGavin.Maltby@Sun.COM {
12511102SGavin.Maltby@Sun.COM ASSERT(iep->ei_refcnt == 0);
12611102SGavin.Maltby@Sun.COM
12711102SGavin.Maltby@Sun.COM nvlist_free(iep->ei_nvl);
12811102SGavin.Maltby@Sun.COM fmev_shdl_free(iep->ei_hdl, iep, sizeof (*iep));
12911102SGavin.Maltby@Sun.COM }
13011102SGavin.Maltby@Sun.COM
13111102SGavin.Maltby@Sun.COM void
fmev_hold(fmev_t ev)13211102SGavin.Maltby@Sun.COM fmev_hold(fmev_t ev)
13311102SGavin.Maltby@Sun.COM {
13411102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
13511102SGavin.Maltby@Sun.COM
13611102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
13711102SGavin.Maltby@Sun.COM
138*12967Sgavin.maltby@oracle.com (void) FMEV_API_ENTER(iep, 1);
13911102SGavin.Maltby@Sun.COM
14011102SGavin.Maltby@Sun.COM atomic_inc_32(&iep->ei_refcnt);
14111102SGavin.Maltby@Sun.COM }
14211102SGavin.Maltby@Sun.COM
14311102SGavin.Maltby@Sun.COM void
fmev_rele(fmev_t ev)14411102SGavin.Maltby@Sun.COM fmev_rele(fmev_t ev)
14511102SGavin.Maltby@Sun.COM {
14611102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
14711102SGavin.Maltby@Sun.COM
14811102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
14911102SGavin.Maltby@Sun.COM
150*12967Sgavin.maltby@oracle.com (void) FMEV_API_ENTER(iep, 1);
15111102SGavin.Maltby@Sun.COM
15211102SGavin.Maltby@Sun.COM if (atomic_dec_32_nv(&iep->ei_refcnt) == 0)
15311102SGavin.Maltby@Sun.COM fmev_free(iep);
15411102SGavin.Maltby@Sun.COM }
15511102SGavin.Maltby@Sun.COM
15611102SGavin.Maltby@Sun.COM fmev_t
fmev_dup(fmev_t ev)15711102SGavin.Maltby@Sun.COM fmev_dup(fmev_t ev)
15811102SGavin.Maltby@Sun.COM {
15911102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
16011102SGavin.Maltby@Sun.COM fmev_impl_t *cp;
16111102SGavin.Maltby@Sun.COM
16211102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
16311102SGavin.Maltby@Sun.COM
164*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(iep, 1))
165*12967Sgavin.maltby@oracle.com return (NULL); /* fmev_errno set */
16611102SGavin.Maltby@Sun.COM
16711102SGavin.Maltby@Sun.COM if (ev == NULL) {
16811102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_API);
16911102SGavin.Maltby@Sun.COM return (NULL);
17011102SGavin.Maltby@Sun.COM }
17111102SGavin.Maltby@Sun.COM
17211102SGavin.Maltby@Sun.COM if ((cp = fmev_shdl_alloc(iep->ei_hdl, sizeof (*iep))) == NULL) {
17311102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_ALLOC);
17411102SGavin.Maltby@Sun.COM return (NULL);
17511102SGavin.Maltby@Sun.COM }
17611102SGavin.Maltby@Sun.COM
17711102SGavin.Maltby@Sun.COM if (nvlist_dup(iep->ei_nvl, &cp->ei_nvl, 0) != 0) {
17811102SGavin.Maltby@Sun.COM fmev_shdl_free(iep->ei_hdl, cp, sizeof (*cp));
17911102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_ALLOC);
18011102SGavin.Maltby@Sun.COM return (NULL);
18111102SGavin.Maltby@Sun.COM }
18211102SGavin.Maltby@Sun.COM
18311102SGavin.Maltby@Sun.COM cp->ei_magic = _FMEVMAGIC;
18411102SGavin.Maltby@Sun.COM cp->ei_hdl = iep->ei_hdl;
18511102SGavin.Maltby@Sun.COM cp->ei_refcnt = 1;
18611102SGavin.Maltby@Sun.COM return (IMPL2FMEV(cp));
18711102SGavin.Maltby@Sun.COM }
18811102SGavin.Maltby@Sun.COM
18911102SGavin.Maltby@Sun.COM nvlist_t *
fmev_attr_list(fmev_t ev)19011102SGavin.Maltby@Sun.COM fmev_attr_list(fmev_t ev)
19111102SGavin.Maltby@Sun.COM {
19211102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
19311102SGavin.Maltby@Sun.COM
19411102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
19511102SGavin.Maltby@Sun.COM
196*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(iep, 1))
197*12967Sgavin.maltby@oracle.com return (NULL); /* fmev_errno set */
19811102SGavin.Maltby@Sun.COM
19911102SGavin.Maltby@Sun.COM if (ev == NULL) {
20011102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_API);
20111102SGavin.Maltby@Sun.COM return (NULL);
20211102SGavin.Maltby@Sun.COM } else if (iep->ei_nvl == NULL) {
20311102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_MALFORMED_EVENT);
20411102SGavin.Maltby@Sun.COM return (NULL);
20511102SGavin.Maltby@Sun.COM }
20611102SGavin.Maltby@Sun.COM
20711102SGavin.Maltby@Sun.COM return (iep->ei_nvl);
20811102SGavin.Maltby@Sun.COM }
20911102SGavin.Maltby@Sun.COM
21011102SGavin.Maltby@Sun.COM const char *
fmev_class(fmev_t ev)21111102SGavin.Maltby@Sun.COM fmev_class(fmev_t ev)
21211102SGavin.Maltby@Sun.COM {
21311102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
21411102SGavin.Maltby@Sun.COM const char *class;
21511102SGavin.Maltby@Sun.COM
21611102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
21711102SGavin.Maltby@Sun.COM
218*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(iep, 1))
219*12967Sgavin.maltby@oracle.com return (NULL); /* fmev_errno set */
22011102SGavin.Maltby@Sun.COM
22111102SGavin.Maltby@Sun.COM if (ev == NULL) {
22211102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_API);
22311102SGavin.Maltby@Sun.COM return ("");
22411102SGavin.Maltby@Sun.COM }
22511102SGavin.Maltby@Sun.COM
22611102SGavin.Maltby@Sun.COM if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, (char **)&class) != 0 ||
22711102SGavin.Maltby@Sun.COM *class == '\0') {
22811102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_MALFORMED_EVENT);
22911102SGavin.Maltby@Sun.COM return ("");
23011102SGavin.Maltby@Sun.COM }
23111102SGavin.Maltby@Sun.COM
23211102SGavin.Maltby@Sun.COM return (class);
23311102SGavin.Maltby@Sun.COM }
23411102SGavin.Maltby@Sun.COM
23511102SGavin.Maltby@Sun.COM fmev_err_t
fmev_timespec(fmev_t ev,struct timespec * tp)23611102SGavin.Maltby@Sun.COM fmev_timespec(fmev_t ev, struct timespec *tp)
23711102SGavin.Maltby@Sun.COM {
23811102SGavin.Maltby@Sun.COM fmev_impl_t *iep = FMEV2IMPL(ev);
23911102SGavin.Maltby@Sun.COM uint64_t timetlimit;
24011102SGavin.Maltby@Sun.COM
24111102SGavin.Maltby@Sun.COM ASSERT(EVENT_VALID(iep));
242*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(iep, 1))
243*12967Sgavin.maltby@oracle.com return (fmev_errno);
24411102SGavin.Maltby@Sun.COM
24511102SGavin.Maltby@Sun.COM #ifdef _LP64
24611102SGavin.Maltby@Sun.COM timetlimit = INT64_MAX;
24711102SGavin.Maltby@Sun.COM #else
24811102SGavin.Maltby@Sun.COM timetlimit = INT32_MAX;
24911102SGavin.Maltby@Sun.COM #endif
25011102SGavin.Maltby@Sun.COM
25111102SGavin.Maltby@Sun.COM if (iep->ei_fmtime[FM_TIME_SEC] > timetlimit)
25211102SGavin.Maltby@Sun.COM return (FMEVERR_OVERFLOW);
25311102SGavin.Maltby@Sun.COM
25411102SGavin.Maltby@Sun.COM tp->tv_sec = (time_t)iep->ei_fmtime[FM_TIME_SEC];
25511102SGavin.Maltby@Sun.COM tp->tv_nsec = (long)iep->ei_fmtime[FM_TIME_NSEC];
25611102SGavin.Maltby@Sun.COM
25711102SGavin.Maltby@Sun.COM return (FMEV_SUCCESS);
25811102SGavin.Maltby@Sun.COM }
25911102SGavin.Maltby@Sun.COM
26011102SGavin.Maltby@Sun.COM uint64_t
fmev_time_sec(fmev_t ev)26111102SGavin.Maltby@Sun.COM fmev_time_sec(fmev_t ev)
26211102SGavin.Maltby@Sun.COM {
26311102SGavin.Maltby@Sun.COM return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_SEC]);
26411102SGavin.Maltby@Sun.COM }
26511102SGavin.Maltby@Sun.COM
26611102SGavin.Maltby@Sun.COM uint64_t
fmev_time_nsec(fmev_t ev)26711102SGavin.Maltby@Sun.COM fmev_time_nsec(fmev_t ev)
26811102SGavin.Maltby@Sun.COM {
26911102SGavin.Maltby@Sun.COM return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_NSEC]);
27011102SGavin.Maltby@Sun.COM }
27111102SGavin.Maltby@Sun.COM
27211102SGavin.Maltby@Sun.COM struct tm *
fmev_localtime(fmev_t ev,struct tm * tm)27311102SGavin.Maltby@Sun.COM fmev_localtime(fmev_t ev, struct tm *tm)
27411102SGavin.Maltby@Sun.COM {
27511102SGavin.Maltby@Sun.COM time_t seconds;
27611102SGavin.Maltby@Sun.COM
27711102SGavin.Maltby@Sun.COM seconds = (time_t)fmev_time_sec(ev);
27811102SGavin.Maltby@Sun.COM return (localtime_r(&seconds, tm));
27911102SGavin.Maltby@Sun.COM }
280*12967Sgavin.maltby@oracle.com
281*12967Sgavin.maltby@oracle.com fmev_shdl_t
fmev_ev2shdl(fmev_t ev)282*12967Sgavin.maltby@oracle.com fmev_ev2shdl(fmev_t ev)
283*12967Sgavin.maltby@oracle.com {
284*12967Sgavin.maltby@oracle.com fmev_impl_t *iep = FMEV2IMPL(ev);
285*12967Sgavin.maltby@oracle.com
286*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(iep, 2))
287*12967Sgavin.maltby@oracle.com return (NULL);
288*12967Sgavin.maltby@oracle.com
289*12967Sgavin.maltby@oracle.com return (iep->ei_hdl);
290*12967Sgavin.maltby@oracle.com }
291