/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* Simple-minded raw event publication from user context. See extensive
* comments in libfmevent.h. These interfaces remain Project Private -
* they have to evolve before rollout to Public levels.
*
* Events are dispatched synchronously using the GPEC sysevent mechanism.
* The caller context must therefore be one in which a sysevent_evc_publish
* (and possibly sysevent_evc_bind if not already bound) is safe. We will
* also allocate and manipulate nvlists.
*
* Since we use GPEC, which has no least privilege awareness, these interfaces
* will only work for would-be producers running as root.
*
* There is no event rate throttling applied, so we rely on producers
* to throttle themselves. A future refinement should apply mandatory
* but tuneable throttling on a per-producer basis. In this first version
* the only throttle is the publication event queue depth - we'll drop
* events when the queue is full.
*
* We can publish over four channels, for privileged/non-privileged and
* (see above) we hardcode priv == B_TRUE and so only two channels are
* actually used, separating higher and lower value streams from privileged
* producers.
*/
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <atomic.h>
#include <errno.h>
#include <pthread.h>
#include <strings.h>
#include "fmev_impl.h"
static struct {
} chaninfo[] = {
{ FMEV_CHAN_USER_NOPRIV_LV, NULL, 0 },
{ FMEV_CHAN_USER_NOPRIV_HV, NULL, 0 },
};
/*
* Called after fork in the new child. We clear the cached event
* channel bindings which are only valid in the process that created
* them.
*/
static void
clear_bindings(void)
{
int i;
}
#pragma init(_fmev_publish_init)
static void
_fmev_publish_init(void)
{
}
static evchan_t *
{
return (*evcpp);
return (NULL);
(void) sysevent_evc_unbind(evc);
return (*evcpp);
}
static fmev_err_t
{
return (FMEVERR_STRING2BIG);
return (FMEV_OK);
}
static fmev_err_t
{
return (FMEVERR_API);
return (FMEVERR_STRING2BIG);
return (FMEV_OK);
}
static fmev_err_t
{
return (FMEVERR_API);
return (FMEVERR_STRING2BIG);
return (FMEV_OK);
}
static fmev_err_t
{
FMEV_OK : FMEVERR_API);
}
const char *
{
return (NULL);
}
static fmev_err_t
{
return (rc);
return (rc);
return (FMEV_OK);
}
{
char *name;
if (ntuples == 0)
return (FMEVERR_INTERNAL);
return (FMEVERR_VARARGS_MALFORMED);
if (ntuples > fmev_va2nvl_maxtuples)
return (FMEVERR_VARARGS_TOOLONG);
return (FMEVERR_ALLOC);
switch (type) {
case DATA_TYPE_BYTE:
break;
case DATA_TYPE_BYTE_ARRAY:
break;
case DATA_TYPE_BOOLEAN_VALUE:
break;
case DATA_TYPE_BOOLEAN_ARRAY:
break;
case DATA_TYPE_INT8:
break;
case DATA_TYPE_INT8_ARRAY:
break;
case DATA_TYPE_UINT8:
break;
case DATA_TYPE_UINT8_ARRAY:
break;
case DATA_TYPE_INT16:
break;
case DATA_TYPE_INT16_ARRAY:
break;
case DATA_TYPE_UINT16:
break;
case DATA_TYPE_UINT16_ARRAY:
break;
case DATA_TYPE_INT32:
break;
case DATA_TYPE_INT32_ARRAY:
break;
case DATA_TYPE_UINT32:
break;
case DATA_TYPE_UINT32_ARRAY:
break;
case DATA_TYPE_INT64:
break;
case DATA_TYPE_INT64_ARRAY:
break;
case DATA_TYPE_UINT64:
break;
case DATA_TYPE_UINT64_ARRAY:
break;
case DATA_TYPE_STRING:
break;
case DATA_TYPE_STRING_ARRAY:
break;
case DATA_TYPE_NVLIST:
break;
case DATA_TYPE_NVLIST_ARRAY:
break;
case DATA_TYPE_HRTIME:
break;
case DATA_TYPE_DOUBLE:
break;
default:
}
if (err)
break; /* terminate on first error */
processed++;
}
return (FMEVERR_VARARGS_MALFORMED);
}
return (FMEV_SUCCESS);
}
static fmev_err_t
{
if (nvl) {
/*
* Enforce NV_UNIQUE_NAME
*/
return (FMEVERR_NVLIST);
} else if (ntuples != 0) {
if (err != FMEV_SUCCESS)
return (err);
} else {
/*
* Even if the caller has no tuples to publish (just an event
* class and subclass), we are going to add some detector
* information so we need some nvlist.
*/
return (FMEVERR_ALLOC);
}
goto done;
}
/*
* Add detector information
*/
rc = FMEVERR_ALLOC;
goto done;
}
/*
* We abuse the GPEC publication arguments as follows:
*
* GPEC argument Our usage
* -------------------- -----------------
* const char *class Raw class
* const char *subclass Raw subclass
* const char *vendor Ruleset name
* const char *pub_name Unused
* nvlist_t *attr_list Event attributes
*/
done:
/* Free a passed in nvlist iff success */
if (rc == FMEV_SUCCESS)
return (rc);
}
{
return (rc); /* any attr not freed */
}
{
return (rc);
if (ntuples != 0)
if (ntuples != 0)
return (rc);
}
static fmev_err_t
{
return (rc);
if (ntuples != 0)
if (ntuples != 0)
return (rc);
}
static fmev_err_t
{
return (rc);
if (ntuples != 0)
if (ntuples != 0)
return (rc);
}