xref: /onnv-gate/usr/src/cmd/picl/plugins/common/piclevent/piclevent.c (revision 2173:ea3cd1374075)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*2173Skd93003  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * PICL plug-in that listens to sysevent and posts picl events
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <limits.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <assert.h>
390Sstevel@tonic-gate #include <alloca.h>
400Sstevel@tonic-gate #include <unistd.h>
410Sstevel@tonic-gate #include <stropts.h>
420Sstevel@tonic-gate #include <syslog.h>
430Sstevel@tonic-gate #include <libdevinfo.h>
440Sstevel@tonic-gate #include <sys/time.h>
450Sstevel@tonic-gate #include <fcntl.h>
460Sstevel@tonic-gate #include <picl.h>
470Sstevel@tonic-gate #include <picltree.h>
480Sstevel@tonic-gate #include <sys/types.h>
490Sstevel@tonic-gate #include <sys/sysinfo.h>
500Sstevel@tonic-gate #include <dirent.h>
510Sstevel@tonic-gate #include <libintl.h>
520Sstevel@tonic-gate #include <sys/sunddi.h>
530Sstevel@tonic-gate #include <sys/stat.h>
540Sstevel@tonic-gate #include <libsysevent.h>
550Sstevel@tonic-gate #include <libnvpair.h>
560Sstevel@tonic-gate #include "piclevent.h"
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  * Plugin registration entry points
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate static void	eventplugin_register(void);
620Sstevel@tonic-gate static void	eventplugin_init(void);
630Sstevel@tonic-gate static void	eventplugin_fini(void);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #pragma	init(eventplugin_register)
660Sstevel@tonic-gate 
670Sstevel@tonic-gate static picld_plugin_reg_t  my_reg_info = {
680Sstevel@tonic-gate 	PICLD_PLUGIN_VERSION_1,
690Sstevel@tonic-gate 	PICLD_PLUGIN_CRITICAL,
700Sstevel@tonic-gate 	"SUNW_piclevent plugin for sysevents",
710Sstevel@tonic-gate 	eventplugin_init,
720Sstevel@tonic-gate 	eventplugin_fini
730Sstevel@tonic-gate };
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate  * Log message texts
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate #define	EVT_THR_FAILED		gettext("Event thread create failed!\n")
790Sstevel@tonic-gate #define	EVT_OPEN_FAILED		gettext("PICL SLM door create failed\n")
800Sstevel@tonic-gate 
810Sstevel@tonic-gate static	int		door_id = -1;
820Sstevel@tonic-gate #define	SUNW_PICLEVENT_PLUGIN_DEBUG	"SUNW_PICLEVENT_PLUGIN_DEBUG"
830Sstevel@tonic-gate static	int		piclevent_debug = 0;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  * completion handler for the posted picl event
880Sstevel@tonic-gate  */
890Sstevel@tonic-gate /*ARGSUSED*/
900Sstevel@tonic-gate static void
piclevent_completion_handler(char * ename,void * earg,size_t size)910Sstevel@tonic-gate piclevent_completion_handler(char *ename, void *earg, size_t size)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	free(earg);
940Sstevel@tonic-gate 	free(ename);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate  * This function posts the incoming piclevent
990Sstevel@tonic-gate  * It packs the nvlist and posts it to PICL
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate static void
parse_piclevent(nvlist_t * nvlp)1020Sstevel@tonic-gate parse_piclevent(nvlist_t *nvlp)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	char		*enval;
1050Sstevel@tonic-gate 	char		*ename;
1060Sstevel@tonic-gate 	size_t		nvl_size;
1070Sstevel@tonic-gate 	char		*packed_nvl;
1080Sstevel@tonic-gate 	int		err;
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_EVENT_NAME, &enval))
1110Sstevel@tonic-gate 		return;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	packed_nvl = NULL;
1140Sstevel@tonic-gate 	if (nvlist_pack(nvlp, &packed_nvl, &nvl_size, NV_ENCODE_NATIVE, NULL))
1150Sstevel@tonic-gate 		return;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	ename = strdup(enval);
1180Sstevel@tonic-gate 	if (ename == NULL) {
1190Sstevel@tonic-gate 		free(packed_nvl);
1200Sstevel@tonic-gate 		return;
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if (piclevent_debug) {
1240Sstevel@tonic-gate 		syslog(LOG_INFO, "piclevent: posting ename:%s packed_nvl:%p "
1250Sstevel@tonic-gate 		    "nvl_size:0x%x\n", ename, packed_nvl, nvl_size);
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 	err = ptree_post_event(ename, packed_nvl, nvl_size,
1280Sstevel@tonic-gate 	    piclevent_completion_handler);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
1310Sstevel@tonic-gate 		if (piclevent_debug)
1320Sstevel@tonic-gate 			syslog(LOG_INFO,
1330Sstevel@tonic-gate 			    "piclevent: posting ename:%s failed err:%d\n",
1340Sstevel@tonic-gate 			    ename, err);
1350Sstevel@tonic-gate 		free(ename);
1360Sstevel@tonic-gate 		free(packed_nvl);
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate  * This is the PICL SLM door handler. It parses the event tuple received
1420Sstevel@tonic-gate  * and posts an event to refresh the PICL tree.
1430Sstevel@tonic-gate  */
1440Sstevel@tonic-gate /*ARGSUSED*/
1450Sstevel@tonic-gate static void
event_handler(void * cookie,char * argp,size_t asize,door_desc_t * dp,uint_t n_desc)1460Sstevel@tonic-gate event_handler(void *cookie, char *argp, size_t asize,
1470Sstevel@tonic-gate     door_desc_t *dp, uint_t n_desc)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate 	door_cred_t		cred;
1500Sstevel@tonic-gate 	nvlist_t		*nvlp;
1510Sstevel@tonic-gate 	char			*dtype;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (piclevent_debug)
1540Sstevel@tonic-gate 		syslog(LOG_INFO,
1550Sstevel@tonic-gate 		    "piclevent: got SLM event cookie:%p evarg:%p size:0x%x\n",
1560Sstevel@tonic-gate 		    cookie, argp, asize);
1570Sstevel@tonic-gate 	if ((door_id < 0) || (argp == NULL) || (door_cred(&cred) < 0) ||
1580Sstevel@tonic-gate 	    (cred.dc_euid != 0))
1590Sstevel@tonic-gate 		(void) door_return(argp, 0, NULL, 0);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if (nvlist_unpack(argp, asize, &nvlp, NULL))
1620Sstevel@tonic-gate 		(void) door_return(argp, 0, NULL, 0);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
1650Sstevel@tonic-gate 		nvlist_free(nvlp);
1660Sstevel@tonic-gate 		(void) door_return(argp, 0, NULL, 0);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) == 0)
1700Sstevel@tonic-gate 		parse_piclevent(nvlp);
1710Sstevel@tonic-gate 	/*
1720Sstevel@tonic-gate 	 * ignore other event data types
1730Sstevel@tonic-gate 	 */
1740Sstevel@tonic-gate 	nvlist_free(nvlp);
1750Sstevel@tonic-gate 	(void) door_return(argp, 0, NULL, 0);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * Create the slm to picl plugin door
1800Sstevel@tonic-gate  */
1810Sstevel@tonic-gate static int
setup_door(void)1820Sstevel@tonic-gate setup_door(void)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate 	struct stat	stbuf;
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	/*
1870Sstevel@tonic-gate 	 * Create the door
1880Sstevel@tonic-gate 	 */
1890Sstevel@tonic-gate 	door_id = door_create(event_handler, PICLEVENT_DOOR_COOKIE,
190*2173Skd93003 	    DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	if (door_id < 0)
1930Sstevel@tonic-gate 		return (-1);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	if (stat(PICLEVENT_DOOR, &stbuf) < 0) {
1960Sstevel@tonic-gate 		int newfd;
1970Sstevel@tonic-gate 		if ((newfd = creat(PICLEVENT_DOOR, 0444)) < 0) {
1980Sstevel@tonic-gate 			(void) door_revoke(door_id);
1990Sstevel@tonic-gate 			door_id = -1;
2000Sstevel@tonic-gate 			return (-1);
2010Sstevel@tonic-gate 		}
2020Sstevel@tonic-gate 		(void) close(newfd);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if (fattach(door_id, PICLEVENT_DOOR) < 0) {
2060Sstevel@tonic-gate 		if ((errno != EBUSY) || (fdetach(PICLEVENT_DOOR) < 0) ||
2070Sstevel@tonic-gate 		    (fattach(door_id, PICLEVENT_DOOR) < 0)) {
2080Sstevel@tonic-gate 			(void) door_revoke(door_id);
2090Sstevel@tonic-gate 			door_id = -1;
2100Sstevel@tonic-gate 			return (-1);
2110Sstevel@tonic-gate 		}
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	return (0);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate  * This function is executed as part of .init when the plugin is
2200Sstevel@tonic-gate  * dlopen()ed
2210Sstevel@tonic-gate  */
2220Sstevel@tonic-gate static void
eventplugin_register(void)2230Sstevel@tonic-gate eventplugin_register(void)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	if (getenv(SUNW_PICLEVENT_PLUGIN_DEBUG))
2260Sstevel@tonic-gate 		piclevent_debug = 1;
2270Sstevel@tonic-gate 	(void) picld_plugin_register(&my_reg_info);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate  * This function is the init entry point of the plugin.
2320Sstevel@tonic-gate  * It creates the slm to picl plugin door.
2330Sstevel@tonic-gate  */
2340Sstevel@tonic-gate static void
eventplugin_init(void)2350Sstevel@tonic-gate eventplugin_init(void)
2360Sstevel@tonic-gate {
2370Sstevel@tonic-gate 	if (setup_door() < 0) {
2380Sstevel@tonic-gate 		syslog(LOG_ERR, EVT_OPEN_FAILED);
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate  * This function is the fini entry point of the plugin
2440Sstevel@tonic-gate  */
2450Sstevel@tonic-gate static void
eventplugin_fini(void)2460Sstevel@tonic-gate eventplugin_fini(void)
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate 	if (door_id >= 0) {
2490Sstevel@tonic-gate 		(void) door_revoke(door_id);
2500Sstevel@tonic-gate 		door_id = -1;
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate }
253