1f6e214c7SGavin Maltby /* 2f6e214c7SGavin Maltby * CDDL HEADER START 3f6e214c7SGavin Maltby * 4f6e214c7SGavin Maltby * The contents of this file are subject to the terms of the 5f6e214c7SGavin Maltby * Common Development and Distribution License (the "License"). 6f6e214c7SGavin Maltby * You may not use this file except in compliance with the License. 7f6e214c7SGavin Maltby * 8f6e214c7SGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f6e214c7SGavin Maltby * or http://www.opensolaris.org/os/licensing. 10f6e214c7SGavin Maltby * See the License for the specific language governing permissions 11f6e214c7SGavin Maltby * and limitations under the License. 12f6e214c7SGavin Maltby * 13f6e214c7SGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each 14f6e214c7SGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f6e214c7SGavin Maltby * If applicable, add the following below this CDDL HEADER, with the 16f6e214c7SGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying 17f6e214c7SGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner] 18f6e214c7SGavin Maltby * 19f6e214c7SGavin Maltby * CDDL HEADER END 20f6e214c7SGavin Maltby */ 21f6e214c7SGavin Maltby 22f6e214c7SGavin Maltby /* 23f6e214c7SGavin Maltby * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24f6e214c7SGavin Maltby */ 25f6e214c7SGavin Maltby 26f6e214c7SGavin Maltby /* 27f6e214c7SGavin Maltby * Simple-minded raw event publication from user context. See extensive 28f6e214c7SGavin Maltby * comments in libfmevent.h. These interfaces remain Project Private - 29f6e214c7SGavin Maltby * they have to evolve before rollout to Public levels. 30f6e214c7SGavin Maltby * 31f6e214c7SGavin Maltby * Events are dispatched synchronously using the GPEC sysevent mechanism. 32f6e214c7SGavin Maltby * The caller context must therefore be one in which a sysevent_evc_publish 33f6e214c7SGavin Maltby * (and possibly sysevent_evc_bind if not already bound) is safe. We will 34f6e214c7SGavin Maltby * also allocate and manipulate nvlists. 35f6e214c7SGavin Maltby * 36f6e214c7SGavin Maltby * Since we use GPEC, which has no least privilege awareness, these interfaces 37f6e214c7SGavin Maltby * will only work for would-be producers running as root. 38f6e214c7SGavin Maltby * 39f6e214c7SGavin Maltby * There is no event rate throttling applied, so we rely on producers 40f6e214c7SGavin Maltby * to throttle themselves. A future refinement should apply mandatory 41f6e214c7SGavin Maltby * but tuneable throttling on a per-producer basis. In this first version 42f6e214c7SGavin Maltby * the only throttle is the publication event queue depth - we'll drop 43f6e214c7SGavin Maltby * events when the queue is full. 44f6e214c7SGavin Maltby * 45f6e214c7SGavin Maltby * We can publish over four channels, for privileged/non-privileged and 46f6e214c7SGavin Maltby * high/low priority. Since only privileged producers will work now 47f6e214c7SGavin Maltby * (see above) we hardcode priv == B_TRUE and so only two channels are 48f6e214c7SGavin Maltby * actually used, separating higher and lower value streams from privileged 49f6e214c7SGavin Maltby * producers. 50f6e214c7SGavin Maltby */ 51f6e214c7SGavin Maltby 52f6e214c7SGavin Maltby #include <stdarg.h> 53f6e214c7SGavin Maltby #include <unistd.h> 54f6e214c7SGavin Maltby #include <stdlib.h> 55f6e214c7SGavin Maltby #include <atomic.h> 56f6e214c7SGavin Maltby #include <errno.h> 57f6e214c7SGavin Maltby #include <pthread.h> 58f6e214c7SGavin Maltby #include <strings.h> 59f6e214c7SGavin Maltby 60f6e214c7SGavin Maltby #include "fmev_impl.h" 61f6e214c7SGavin Maltby 62f6e214c7SGavin Maltby static struct { 63f6e214c7SGavin Maltby const char *name; /* channel name */ 64f6e214c7SGavin Maltby evchan_t *binding; /* GPEC binding, once bound */ 65f6e214c7SGavin Maltby const uint32_t flags; /* flags to use in binding */ 66f6e214c7SGavin Maltby } chaninfo[] = { 67f6e214c7SGavin Maltby { FMEV_CHAN_USER_NOPRIV_LV, NULL, 0 }, 68f6e214c7SGavin Maltby { FMEV_CHAN_USER_NOPRIV_HV, NULL, 0 }, 69f6e214c7SGavin Maltby { FMEV_CHAN_USER_PRIV_LV, NULL, EVCH_HOLD_PEND_INDEF }, 70f6e214c7SGavin Maltby { FMEV_CHAN_USER_PRIV_HV, NULL, EVCH_HOLD_PEND_INDEF} 71f6e214c7SGavin Maltby }; 72f6e214c7SGavin Maltby 73f6e214c7SGavin Maltby #define CHANIDX(priv, pri) (2 * ((priv) != 0) + (pri == FMEV_HIPRI)) 74f6e214c7SGavin Maltby 75f6e214c7SGavin Maltby #define CHAN_NAME(priv, pri) (chaninfo[CHANIDX(priv, pri)].name) 76f6e214c7SGavin Maltby #define CHAN_BINDING(priv, pri) (chaninfo[CHANIDX(priv, pri)].binding) 77f6e214c7SGavin Maltby #define CHAN_FLAGS(priv, pri) (chaninfo[CHANIDX(priv, pri)].flags) 78f6e214c7SGavin Maltby 79f6e214c7SGavin Maltby /* 80f6e214c7SGavin Maltby * Called after fork in the new child. We clear the cached event 81f6e214c7SGavin Maltby * channel bindings which are only valid in the process that created 82f6e214c7SGavin Maltby * them. 83f6e214c7SGavin Maltby */ 84f6e214c7SGavin Maltby static void 85f6e214c7SGavin Maltby clear_bindings(void) 86f6e214c7SGavin Maltby { 87f6e214c7SGavin Maltby int i; 88f6e214c7SGavin Maltby 89f6e214c7SGavin Maltby for (i = 0; i < sizeof (chaninfo) / sizeof chaninfo[0]; i++) 90f6e214c7SGavin Maltby chaninfo[i].binding = NULL; 91f6e214c7SGavin Maltby } 92f6e214c7SGavin Maltby 93f6e214c7SGavin Maltby #pragma init(_fmev_publish_init) 94f6e214c7SGavin Maltby 95f6e214c7SGavin Maltby static void 96f6e214c7SGavin Maltby _fmev_publish_init(void) 97f6e214c7SGavin Maltby { 98f6e214c7SGavin Maltby (void) pthread_atfork(NULL, NULL, clear_bindings); 99f6e214c7SGavin Maltby } 100f6e214c7SGavin Maltby 101f6e214c7SGavin Maltby static evchan_t * 102f6e214c7SGavin Maltby bind_channel(boolean_t priv, fmev_pri_t pri) 103f6e214c7SGavin Maltby { 104f6e214c7SGavin Maltby evchan_t **evcpp = &CHAN_BINDING(priv, pri); 105f6e214c7SGavin Maltby evchan_t *evc; 106f6e214c7SGavin Maltby 107f6e214c7SGavin Maltby if (*evcpp != NULL) 108f6e214c7SGavin Maltby return (*evcpp); 109f6e214c7SGavin Maltby 110f6e214c7SGavin Maltby if (sysevent_evc_bind(CHAN_NAME(priv, pri), &evc, 111f6e214c7SGavin Maltby EVCH_CREAT | CHAN_FLAGS(priv, pri)) != 0) 112f6e214c7SGavin Maltby return (NULL); 113f6e214c7SGavin Maltby 114f6e214c7SGavin Maltby if (atomic_cas_ptr(evcpp, NULL, evc) != NULL) 115f6e214c7SGavin Maltby (void) sysevent_evc_unbind(evc); 116f6e214c7SGavin Maltby 117f6e214c7SGavin Maltby return (*evcpp); 118f6e214c7SGavin Maltby } 119f6e214c7SGavin Maltby 120f6e214c7SGavin Maltby static fmev_err_t 121f6e214c7SGavin Maltby vrfy_ruleset(const char *ruleset) 122f6e214c7SGavin Maltby { 123f6e214c7SGavin Maltby if (ruleset != NULL && 124f6e214c7SGavin Maltby strnlen(ruleset, FMEV_MAX_RULESET_LEN) == FMEV_MAX_RULESET_LEN) 125f6e214c7SGavin Maltby return (FMEVERR_STRING2BIG); 126f6e214c7SGavin Maltby 127f6e214c7SGavin Maltby return (FMEV_OK); 128f6e214c7SGavin Maltby 129f6e214c7SGavin Maltby } 130f6e214c7SGavin Maltby 131f6e214c7SGavin Maltby static fmev_err_t 132f6e214c7SGavin Maltby vrfy_class(const char *class) 133f6e214c7SGavin Maltby { 134f6e214c7SGavin Maltby if (class == NULL || *class == '\0') 135f6e214c7SGavin Maltby return (FMEVERR_API); 136f6e214c7SGavin Maltby 137f6e214c7SGavin Maltby if (strnlen(class, FMEV_PUB_MAXCLASSLEN) == FMEV_PUB_MAXCLASSLEN) 138f6e214c7SGavin Maltby return (FMEVERR_STRING2BIG); 139f6e214c7SGavin Maltby 140f6e214c7SGavin Maltby return (FMEV_OK); 141f6e214c7SGavin Maltby } 142f6e214c7SGavin Maltby 143f6e214c7SGavin Maltby static fmev_err_t 144f6e214c7SGavin Maltby vrfy_subclass(const char *subclass) 145f6e214c7SGavin Maltby { 146f6e214c7SGavin Maltby if (subclass == NULL || *subclass == '\0') 147f6e214c7SGavin Maltby return (FMEVERR_API); 148f6e214c7SGavin Maltby 149f6e214c7SGavin Maltby if (strnlen(subclass, FMEV_PUB_MAXSUBCLASSLEN) == 150f6e214c7SGavin Maltby FMEV_PUB_MAXSUBCLASSLEN) 151f6e214c7SGavin Maltby return (FMEVERR_STRING2BIG); 152f6e214c7SGavin Maltby 153f6e214c7SGavin Maltby return (FMEV_OK); 154f6e214c7SGavin Maltby } 155f6e214c7SGavin Maltby 156f6e214c7SGavin Maltby static fmev_err_t 157f6e214c7SGavin Maltby vrfy_pri(fmev_pri_t pri) 158f6e214c7SGavin Maltby { 159f6e214c7SGavin Maltby return (pri == FMEV_LOPRI || pri == FMEV_HIPRI ? 160f6e214c7SGavin Maltby FMEV_OK : FMEVERR_API); 161f6e214c7SGavin Maltby } 162f6e214c7SGavin Maltby 163f6e214c7SGavin Maltby const char * 164f6e214c7SGavin Maltby fmev_pri_string(fmev_pri_t pri) 165f6e214c7SGavin Maltby { 166f6e214c7SGavin Maltby static const char *pristr[] = { "low", "high" }; 167f6e214c7SGavin Maltby 168f6e214c7SGavin Maltby if (vrfy_pri(pri) != FMEV_OK) 169f6e214c7SGavin Maltby return (NULL); 170f6e214c7SGavin Maltby 171f6e214c7SGavin Maltby return (pristr[pri - FMEV_LOPRI]); 172f6e214c7SGavin Maltby } 173f6e214c7SGavin Maltby 174f6e214c7SGavin Maltby static fmev_err_t 175f6e214c7SGavin Maltby vrfy(const char **rulesetp, const char **classp, const char **subclassp, 176f6e214c7SGavin Maltby fmev_pri_t *prip) 177f6e214c7SGavin Maltby { 178f6e214c7SGavin Maltby fmev_err_t rc = FMEV_OK; 179f6e214c7SGavin Maltby 180f6e214c7SGavin Maltby if (rulesetp && (rc = vrfy_ruleset(*rulesetp)) != FMEV_OK) 181f6e214c7SGavin Maltby return (rc); 182f6e214c7SGavin Maltby 183f6e214c7SGavin Maltby if (classp && (rc = vrfy_class(*classp)) != FMEV_OK || 184f6e214c7SGavin Maltby subclassp && (rc = vrfy_subclass(*subclassp)) != FMEV_OK || 185f6e214c7SGavin Maltby prip && (rc = vrfy_pri(*prip)) != FMEV_OK) 186f6e214c7SGavin Maltby return (rc); 187f6e214c7SGavin Maltby 188f6e214c7SGavin Maltby return (FMEV_OK); 189f6e214c7SGavin Maltby } 190f6e214c7SGavin Maltby 191f6e214c7SGavin Maltby uint_t fmev_va2nvl_maxtuples = 100; 192f6e214c7SGavin Maltby 193f6e214c7SGavin Maltby fmev_err_t 194f6e214c7SGavin Maltby va2nvl(nvlist_t **nvlp, va_list ap, uint_t ntuples) 195f6e214c7SGavin Maltby { 196f6e214c7SGavin Maltby nvlist_t *nvl = NULL; 197f6e214c7SGavin Maltby uint_t processed = 0; 198f6e214c7SGavin Maltby char *name; 199f6e214c7SGavin Maltby 200f6e214c7SGavin Maltby if (ntuples == 0) 201f6e214c7SGavin Maltby return (FMEVERR_INTERNAL); 202f6e214c7SGavin Maltby 203f6e214c7SGavin Maltby if ((name = va_arg(ap, char *)) == NULL || name == FMEV_ARG_TERM) 204f6e214c7SGavin Maltby return (FMEVERR_VARARGS_MALFORMED); 205f6e214c7SGavin Maltby 206f6e214c7SGavin Maltby if (ntuples > fmev_va2nvl_maxtuples) 207f6e214c7SGavin Maltby return (FMEVERR_VARARGS_TOOLONG); 208f6e214c7SGavin Maltby 209f6e214c7SGavin Maltby if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 210f6e214c7SGavin Maltby return (FMEVERR_ALLOC); 211f6e214c7SGavin Maltby 212f6e214c7SGavin Maltby while (name != NULL && name != FMEV_ARG_TERM && processed <= ntuples) { 213f6e214c7SGavin Maltby data_type_t type; 214f6e214c7SGavin Maltby int err, nelem; 215f6e214c7SGavin Maltby 216f6e214c7SGavin Maltby type = va_arg(ap, data_type_t); 217f6e214c7SGavin Maltby 218f6e214c7SGavin Maltby switch (type) { 219f6e214c7SGavin Maltby case DATA_TYPE_BYTE: 220f6e214c7SGavin Maltby err = nvlist_add_byte(nvl, name, 221f6e214c7SGavin Maltby va_arg(ap, uint_t)); 222f6e214c7SGavin Maltby break; 223f6e214c7SGavin Maltby case DATA_TYPE_BYTE_ARRAY: 224f6e214c7SGavin Maltby nelem = va_arg(ap, int); 225f6e214c7SGavin Maltby err = nvlist_add_byte_array(nvl, name, 226f6e214c7SGavin Maltby va_arg(ap, uchar_t *), nelem); 227f6e214c7SGavin Maltby break; 228f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_VALUE: 229f6e214c7SGavin Maltby err = nvlist_add_boolean_value(nvl, name, 230f6e214c7SGavin Maltby va_arg(ap, boolean_t)); 231f6e214c7SGavin Maltby break; 232f6e214c7SGavin Maltby case DATA_TYPE_BOOLEAN_ARRAY: 233f6e214c7SGavin Maltby nelem = va_arg(ap, int); 234f6e214c7SGavin Maltby err = nvlist_add_boolean_array(nvl, name, 235f6e214c7SGavin Maltby va_arg(ap, boolean_t *), nelem); 236f6e214c7SGavin Maltby break; 237f6e214c7SGavin Maltby case DATA_TYPE_INT8: 238f6e214c7SGavin Maltby err = nvlist_add_int8(nvl, name, 239f6e214c7SGavin Maltby va_arg(ap, int)); 240f6e214c7SGavin Maltby break; 241f6e214c7SGavin Maltby case DATA_TYPE_INT8_ARRAY: 242f6e214c7SGavin Maltby nelem = va_arg(ap, int); 243f6e214c7SGavin Maltby err = nvlist_add_int8_array(nvl, name, 244f6e214c7SGavin Maltby va_arg(ap, int8_t *), nelem); 245f6e214c7SGavin Maltby break; 246f6e214c7SGavin Maltby case DATA_TYPE_UINT8: 247f6e214c7SGavin Maltby err = nvlist_add_uint8(nvl, name, 248f6e214c7SGavin Maltby va_arg(ap, uint_t)); 249f6e214c7SGavin Maltby break; 250f6e214c7SGavin Maltby case DATA_TYPE_UINT8_ARRAY: 251f6e214c7SGavin Maltby nelem = va_arg(ap, int); 252f6e214c7SGavin Maltby err = nvlist_add_uint8_array(nvl, name, 253f6e214c7SGavin Maltby va_arg(ap, uint8_t *), nelem); 254f6e214c7SGavin Maltby break; 255f6e214c7SGavin Maltby case DATA_TYPE_INT16: 256f6e214c7SGavin Maltby err = nvlist_add_int16(nvl, name, 257f6e214c7SGavin Maltby va_arg(ap, int)); 258f6e214c7SGavin Maltby break; 259f6e214c7SGavin Maltby case DATA_TYPE_INT16_ARRAY: 260f6e214c7SGavin Maltby nelem = va_arg(ap, int); 261f6e214c7SGavin Maltby err = nvlist_add_int16_array(nvl, name, 262f6e214c7SGavin Maltby va_arg(ap, int16_t *), nelem); 263f6e214c7SGavin Maltby break; 264f6e214c7SGavin Maltby case DATA_TYPE_UINT16: 265f6e214c7SGavin Maltby err = nvlist_add_uint16(nvl, name, 266f6e214c7SGavin Maltby va_arg(ap, uint_t)); 267f6e214c7SGavin Maltby break; 268f6e214c7SGavin Maltby case DATA_TYPE_UINT16_ARRAY: 269f6e214c7SGavin Maltby nelem = va_arg(ap, int); 270f6e214c7SGavin Maltby err = nvlist_add_uint16_array(nvl, name, 271f6e214c7SGavin Maltby va_arg(ap, uint16_t *), nelem); 272f6e214c7SGavin Maltby break; 273f6e214c7SGavin Maltby case DATA_TYPE_INT32: 274f6e214c7SGavin Maltby err = nvlist_add_int32(nvl, name, 275f6e214c7SGavin Maltby va_arg(ap, int32_t)); 276f6e214c7SGavin Maltby break; 277f6e214c7SGavin Maltby case DATA_TYPE_INT32_ARRAY: 278f6e214c7SGavin Maltby nelem = va_arg(ap, int); 279f6e214c7SGavin Maltby err = nvlist_add_int32_array(nvl, name, 280f6e214c7SGavin Maltby va_arg(ap, int32_t *), nelem); 281f6e214c7SGavin Maltby break; 282f6e214c7SGavin Maltby case DATA_TYPE_UINT32: 283f6e214c7SGavin Maltby err = nvlist_add_uint32(nvl, name, 284f6e214c7SGavin Maltby va_arg(ap, uint32_t)); 285f6e214c7SGavin Maltby break; 286f6e214c7SGavin Maltby case DATA_TYPE_UINT32_ARRAY: 287f6e214c7SGavin Maltby nelem = va_arg(ap, int); 288f6e214c7SGavin Maltby err = nvlist_add_uint32_array(nvl, name, 289f6e214c7SGavin Maltby va_arg(ap, uint32_t *), nelem); 290f6e214c7SGavin Maltby break; 291f6e214c7SGavin Maltby case DATA_TYPE_INT64: 292f6e214c7SGavin Maltby err = nvlist_add_int64(nvl, name, 293f6e214c7SGavin Maltby va_arg(ap, int64_t)); 294f6e214c7SGavin Maltby break; 295f6e214c7SGavin Maltby case DATA_TYPE_INT64_ARRAY: 296f6e214c7SGavin Maltby nelem = va_arg(ap, int); 297f6e214c7SGavin Maltby err = nvlist_add_int64_array(nvl, name, 298f6e214c7SGavin Maltby va_arg(ap, int64_t *), nelem); 299f6e214c7SGavin Maltby break; 300f6e214c7SGavin Maltby case DATA_TYPE_UINT64: 301f6e214c7SGavin Maltby err = nvlist_add_uint64(nvl, name, 302f6e214c7SGavin Maltby va_arg(ap, uint64_t)); 303f6e214c7SGavin Maltby break; 304f6e214c7SGavin Maltby case DATA_TYPE_UINT64_ARRAY: 305f6e214c7SGavin Maltby nelem = va_arg(ap, int); 306f6e214c7SGavin Maltby err = nvlist_add_uint64_array(nvl, name, 307f6e214c7SGavin Maltby va_arg(ap, uint64_t *), nelem); 308f6e214c7SGavin Maltby break; 309f6e214c7SGavin Maltby case DATA_TYPE_STRING: 310f6e214c7SGavin Maltby err = nvlist_add_string(nvl, name, 311f6e214c7SGavin Maltby va_arg(ap, char *)); 312f6e214c7SGavin Maltby break; 313f6e214c7SGavin Maltby case DATA_TYPE_STRING_ARRAY: 314f6e214c7SGavin Maltby nelem = va_arg(ap, int); 315f6e214c7SGavin Maltby err = nvlist_add_string_array(nvl, name, 316f6e214c7SGavin Maltby va_arg(ap, char **), nelem); 317f6e214c7SGavin Maltby break; 318f6e214c7SGavin Maltby case DATA_TYPE_NVLIST: 319f6e214c7SGavin Maltby err = nvlist_add_nvlist(nvl, name, 320f6e214c7SGavin Maltby va_arg(ap, nvlist_t *)); 321f6e214c7SGavin Maltby break; 322f6e214c7SGavin Maltby case DATA_TYPE_NVLIST_ARRAY: 323f6e214c7SGavin Maltby nelem = va_arg(ap, int); 324f6e214c7SGavin Maltby err = nvlist_add_nvlist_array(nvl, name, 325f6e214c7SGavin Maltby va_arg(ap, nvlist_t **), nelem); 326f6e214c7SGavin Maltby break; 327f6e214c7SGavin Maltby case DATA_TYPE_HRTIME: 328f6e214c7SGavin Maltby err = nvlist_add_hrtime(nvl, name, 329f6e214c7SGavin Maltby va_arg(ap, hrtime_t)); 330f6e214c7SGavin Maltby break; 331f6e214c7SGavin Maltby case DATA_TYPE_DOUBLE: 332f6e214c7SGavin Maltby err = nvlist_add_double(nvl, name, 333f6e214c7SGavin Maltby va_arg(ap, double)); 334f6e214c7SGavin Maltby break; 335f6e214c7SGavin Maltby default: 336f6e214c7SGavin Maltby err = EINVAL; 337f6e214c7SGavin Maltby } 338f6e214c7SGavin Maltby 339f6e214c7SGavin Maltby if (err) 340f6e214c7SGavin Maltby break; /* terminate on first error */ 341f6e214c7SGavin Maltby 342f6e214c7SGavin Maltby processed++; 343f6e214c7SGavin Maltby name = va_arg(ap, char *); 344f6e214c7SGavin Maltby } 345f6e214c7SGavin Maltby 346f6e214c7SGavin Maltby if (name != FMEV_ARG_TERM || processed != ntuples) { 347f6e214c7SGavin Maltby *nvlp = NULL; 348f6e214c7SGavin Maltby nvlist_free(nvl); 349f6e214c7SGavin Maltby return (FMEVERR_VARARGS_MALFORMED); 350f6e214c7SGavin Maltby } 351f6e214c7SGavin Maltby 352f6e214c7SGavin Maltby *nvlp = nvl; 353f6e214c7SGavin Maltby return (FMEV_SUCCESS); 354f6e214c7SGavin Maltby } 355f6e214c7SGavin Maltby 356f6e214c7SGavin Maltby static fmev_err_t 357f6e214c7SGavin Maltby do_publish(const char *file, const char *func, int64_t line, 358f6e214c7SGavin Maltby const char *ruleset, const char *class, const char *subclass, 359f6e214c7SGavin Maltby fmev_pri_t pri, nvlist_t *nvl, uint_t ntuples, va_list ap) 360f6e214c7SGavin Maltby { 361f6e214c7SGavin Maltby fmev_err_t rc = FMEVERR_INTERNAL; 362f6e214c7SGavin Maltby boolean_t priv = B_TRUE; 363f6e214c7SGavin Maltby nvlist_t *tmpnvl = NULL; 364f6e214c7SGavin Maltby nvlist_t *pub; 365f6e214c7SGavin Maltby evchan_t *evc; 366f6e214c7SGavin Maltby 367f6e214c7SGavin Maltby if (nvl) { 368f6e214c7SGavin Maltby ASSERT(ntuples == 0); 369f6e214c7SGavin Maltby 370f6e214c7SGavin Maltby /* 371f6e214c7SGavin Maltby * Enforce NV_UNIQUE_NAME 372f6e214c7SGavin Maltby */ 373f6e214c7SGavin Maltby if ((nvlist_nvflag(nvl) & NV_UNIQUE_NAME) != NV_UNIQUE_NAME) 374f6e214c7SGavin Maltby return (FMEVERR_NVLIST); 375f6e214c7SGavin Maltby 376f6e214c7SGavin Maltby pub = nvl; 377f6e214c7SGavin Maltby 378f6e214c7SGavin Maltby } else if (ntuples != 0) { 379f6e214c7SGavin Maltby fmev_err_t err; 380f6e214c7SGavin Maltby 381f6e214c7SGavin Maltby err = va2nvl(&tmpnvl, ap, ntuples); 382f6e214c7SGavin Maltby if (err != FMEV_SUCCESS) 383f6e214c7SGavin Maltby return (err); 384f6e214c7SGavin Maltby 385f6e214c7SGavin Maltby pub = tmpnvl; 386f6e214c7SGavin Maltby } else { 387f6e214c7SGavin Maltby /* 388f6e214c7SGavin Maltby * Even if the caller has no tuples to publish (just an event 389f6e214c7SGavin Maltby * class and subclass), we are going to add some detector 390f6e214c7SGavin Maltby * information so we need some nvlist. 391f6e214c7SGavin Maltby */ 392f6e214c7SGavin Maltby if (nvlist_alloc(&tmpnvl, NV_UNIQUE_NAME, 0) != 0) 393f6e214c7SGavin Maltby return (FMEVERR_ALLOC); 394f6e214c7SGavin Maltby 395f6e214c7SGavin Maltby pub = tmpnvl; 396f6e214c7SGavin Maltby } 397f6e214c7SGavin Maltby 398f6e214c7SGavin Maltby evc = bind_channel(priv, pri); 399f6e214c7SGavin Maltby 400f6e214c7SGavin Maltby if (evc == NULL) { 401f6e214c7SGavin Maltby rc = FMEVERR_INTERNAL; 402f6e214c7SGavin Maltby goto done; 403f6e214c7SGavin Maltby } 404f6e214c7SGavin Maltby 405f6e214c7SGavin Maltby 406f6e214c7SGavin Maltby /* 407f6e214c7SGavin Maltby * Add detector information 408f6e214c7SGavin Maltby */ 409f6e214c7SGavin Maltby if (file && nvlist_add_string(pub, "__fmev_file", file) != 0 || 410f6e214c7SGavin Maltby func && nvlist_add_string(pub, "__fmev_func", func) != 0 || 411f6e214c7SGavin Maltby line != -1 && nvlist_add_int64(pub, "__fmev_line", line) != 0 || 412f6e214c7SGavin Maltby nvlist_add_int32(pub, "__fmev_pid", getpid()) != 0 || 413f6e214c7SGavin Maltby nvlist_add_string(pub, "__fmev_execname", getexecname()) != 0) { 414f6e214c7SGavin Maltby rc = FMEVERR_ALLOC; 415f6e214c7SGavin Maltby goto done; 416f6e214c7SGavin Maltby } 417f6e214c7SGavin Maltby 418f6e214c7SGavin Maltby if (ruleset == NULL) 419f6e214c7SGavin Maltby ruleset = FMEV_RULESET_DEFAULT; 420f6e214c7SGavin Maltby 421f6e214c7SGavin Maltby /* 422f6e214c7SGavin Maltby * We abuse the GPEC publication arguments as follows: 423f6e214c7SGavin Maltby * 424f6e214c7SGavin Maltby * GPEC argument Our usage 425f6e214c7SGavin Maltby * -------------------- ----------------- 426f6e214c7SGavin Maltby * const char *class Raw class 427f6e214c7SGavin Maltby * const char *subclass Raw subclass 428f6e214c7SGavin Maltby * const char *vendor Ruleset name 429f6e214c7SGavin Maltby * const char *pub_name Unused 430f6e214c7SGavin Maltby * nvlist_t *attr_list Event attributes 431f6e214c7SGavin Maltby */ 432f6e214c7SGavin Maltby rc = (sysevent_evc_publish(evc, class, subclass, ruleset, "", 433f6e214c7SGavin Maltby pub, EVCH_NOSLEEP) == 0) ? FMEV_SUCCESS : FMEVERR_TRANSPORT; 434f6e214c7SGavin Maltby 435f6e214c7SGavin Maltby done: 436f6e214c7SGavin Maltby /* Free a passed in nvlist iff success */ 437*aab83bb8SJosef 'Jeff' Sipek if (rc == FMEV_SUCCESS) 438f6e214c7SGavin Maltby nvlist_free(nvl); 439f6e214c7SGavin Maltby 440f6e214c7SGavin Maltby nvlist_free(tmpnvl); 441f6e214c7SGavin Maltby 442f6e214c7SGavin Maltby return (rc); 443f6e214c7SGavin Maltby } 444f6e214c7SGavin Maltby 445f6e214c7SGavin Maltby fmev_err_t 446f6e214c7SGavin Maltby _i_fmev_publish_nvl( 447f6e214c7SGavin Maltby const char *file, const char *func, int64_t line, 448f6e214c7SGavin Maltby const char *ruleset, const char *class, const char *subclass, 449f6e214c7SGavin Maltby fmev_pri_t pri, nvlist_t *attr) 450f6e214c7SGavin Maltby { 451f6e214c7SGavin Maltby fmev_err_t rc; 452f6e214c7SGavin Maltby 453f6e214c7SGavin Maltby if ((rc = vrfy(&ruleset, &class, &subclass, &pri)) != FMEV_OK) 454f6e214c7SGavin Maltby return (rc); /* any attr not freed */ 455f6e214c7SGavin Maltby 456f6e214c7SGavin Maltby return (do_publish(file, func, line, 457f6e214c7SGavin Maltby ruleset, class, subclass, 458f6e214c7SGavin Maltby pri, attr, 0, NULL)); /* any attr freed iff success */ 459f6e214c7SGavin Maltby } 460f6e214c7SGavin Maltby 461f6e214c7SGavin Maltby fmev_err_t 462f6e214c7SGavin Maltby _i_fmev_publish( 463f6e214c7SGavin Maltby const char *file, const char *func, int64_t line, 464f6e214c7SGavin Maltby const char *ruleset, const char *class, const char *subclass, 465f6e214c7SGavin Maltby fmev_pri_t pri, 466f6e214c7SGavin Maltby uint_t ntuples, ...) 467f6e214c7SGavin Maltby { 468f6e214c7SGavin Maltby va_list ap; 469f6e214c7SGavin Maltby fmev_err_t rc; 470f6e214c7SGavin Maltby 471f6e214c7SGavin Maltby if ((rc = vrfy(&ruleset, &class, &subclass, &pri)) != FMEV_OK) 472f6e214c7SGavin Maltby return (rc); 473f6e214c7SGavin Maltby 474f6e214c7SGavin Maltby if (ntuples != 0) 475f6e214c7SGavin Maltby va_start(ap, ntuples); 476f6e214c7SGavin Maltby 477f6e214c7SGavin Maltby rc = do_publish(file, func, line, 478f6e214c7SGavin Maltby ruleset, class, subclass, 479f6e214c7SGavin Maltby pri, NULL, ntuples, ap); 480f6e214c7SGavin Maltby 481f6e214c7SGavin Maltby if (ntuples != 0) 482f6e214c7SGavin Maltby va_end(ap); 483f6e214c7SGavin Maltby 484f6e214c7SGavin Maltby return (rc); 485f6e214c7SGavin Maltby } 486f6e214c7SGavin Maltby 487f6e214c7SGavin Maltby 488f6e214c7SGavin Maltby #pragma weak fmev_publish = _fmev_publish 489f6e214c7SGavin Maltby #pragma weak fmev_rspublish = _fmev_rspublish 490f6e214c7SGavin Maltby 491f6e214c7SGavin Maltby static fmev_err_t 492f6e214c7SGavin Maltby _fmev_publish(const char *class, const char *subclass, fmev_pri_t pri, 493f6e214c7SGavin Maltby uint_t ntuples, ...) 494f6e214c7SGavin Maltby { 495f6e214c7SGavin Maltby fmev_err_t rc; 496f6e214c7SGavin Maltby va_list ap; 497f6e214c7SGavin Maltby 498f6e214c7SGavin Maltby if ((rc = vrfy(NULL, &class, &subclass, &pri)) != FMEV_OK) 499f6e214c7SGavin Maltby return (rc); 500f6e214c7SGavin Maltby 501f6e214c7SGavin Maltby if (ntuples != 0) 502f6e214c7SGavin Maltby va_start(ap, ntuples); 503f6e214c7SGavin Maltby 504f6e214c7SGavin Maltby rc = do_publish(NULL, NULL, -1, 505f6e214c7SGavin Maltby FMEV_RULESET_DEFAULT, class, subclass, 506f6e214c7SGavin Maltby pri, NULL, ntuples, ap); 507f6e214c7SGavin Maltby 508f6e214c7SGavin Maltby if (ntuples != 0) 509f6e214c7SGavin Maltby va_end(ap); 510f6e214c7SGavin Maltby 511f6e214c7SGavin Maltby return (rc); 512f6e214c7SGavin Maltby } 513f6e214c7SGavin Maltby 514f6e214c7SGavin Maltby static fmev_err_t 515f6e214c7SGavin Maltby _fmev_rspublish(const char *ruleset, const char *class, const char *subclass, 516f6e214c7SGavin Maltby fmev_pri_t pri, uint_t ntuples, ...) 517f6e214c7SGavin Maltby { 518f6e214c7SGavin Maltby fmev_err_t rc; 519f6e214c7SGavin Maltby va_list ap; 520f6e214c7SGavin Maltby 521f6e214c7SGavin Maltby if ((rc = vrfy(&ruleset, &class, &subclass, &pri)) != FMEV_OK) 522f6e214c7SGavin Maltby return (rc); 523f6e214c7SGavin Maltby 524f6e214c7SGavin Maltby if (ntuples != 0) 525f6e214c7SGavin Maltby va_start(ap, ntuples); 526f6e214c7SGavin Maltby 527f6e214c7SGavin Maltby rc = do_publish(NULL, NULL, -1, 528f6e214c7SGavin Maltby ruleset, class, subclass, 529f6e214c7SGavin Maltby pri, NULL, ntuples, ap); 530f6e214c7SGavin Maltby 531f6e214c7SGavin Maltby if (ntuples != 0) 532f6e214c7SGavin Maltby va_end(ap); 533f6e214c7SGavin Maltby 534f6e214c7SGavin Maltby return (rc); 535f6e214c7SGavin Maltby } 536