xref: /onnv-gate/usr/src/cmd/cmd-inet/lib/nwamd/sysevent_events.c (revision 11918:567043034562)
111767SAnurag.Maskey@Sun.COM /*
211767SAnurag.Maskey@Sun.COM  * CDDL HEADER START
311767SAnurag.Maskey@Sun.COM  *
411767SAnurag.Maskey@Sun.COM  * The contents of this file are subject to the terms of the
511767SAnurag.Maskey@Sun.COM  * Common Development and Distribution License (the "License").
611767SAnurag.Maskey@Sun.COM  * You may not use this file except in compliance with the License.
711767SAnurag.Maskey@Sun.COM  *
811767SAnurag.Maskey@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911767SAnurag.Maskey@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011767SAnurag.Maskey@Sun.COM  * See the License for the specific language governing permissions
1111767SAnurag.Maskey@Sun.COM  * and limitations under the License.
1211767SAnurag.Maskey@Sun.COM  *
1311767SAnurag.Maskey@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411767SAnurag.Maskey@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511767SAnurag.Maskey@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611767SAnurag.Maskey@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711767SAnurag.Maskey@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811767SAnurag.Maskey@Sun.COM  *
1911767SAnurag.Maskey@Sun.COM  * CDDL HEADER END
2011767SAnurag.Maskey@Sun.COM  */
2111767SAnurag.Maskey@Sun.COM 
2211767SAnurag.Maskey@Sun.COM /*
2311767SAnurag.Maskey@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2411767SAnurag.Maskey@Sun.COM  * Use is subject to license terms.
2511767SAnurag.Maskey@Sun.COM  */
2611767SAnurag.Maskey@Sun.COM 
2711767SAnurag.Maskey@Sun.COM #include <assert.h>
2811767SAnurag.Maskey@Sun.COM #include <errno.h>
2911767SAnurag.Maskey@Sun.COM #include <libsysevent.h>
3011767SAnurag.Maskey@Sun.COM #include <sys/sysevent/eventdefs.h>
3111767SAnurag.Maskey@Sun.COM #include <sys/sysevent/dev.h>
3211767SAnurag.Maskey@Sun.COM #include <sys/types.h>
3311767SAnurag.Maskey@Sun.COM #include <libnvpair.h>
3411767SAnurag.Maskey@Sun.COM #include <string.h>
3511767SAnurag.Maskey@Sun.COM #include <unistd.h>
3611767SAnurag.Maskey@Sun.COM 
3711767SAnurag.Maskey@Sun.COM #include "events.h"
3811767SAnurag.Maskey@Sun.COM #include "ncp.h"
3911767SAnurag.Maskey@Sun.COM #include "ncu.h"
4011767SAnurag.Maskey@Sun.COM #include "objects.h"
4111767SAnurag.Maskey@Sun.COM #include "util.h"
4211767SAnurag.Maskey@Sun.COM 
4311767SAnurag.Maskey@Sun.COM /*
4411767SAnurag.Maskey@Sun.COM  * sysevent_events.c - this file contains routines to retrieve sysevents
4511767SAnurag.Maskey@Sun.COM  * from the system and package them for high level processing.
4611767SAnurag.Maskey@Sun.COM  */
4711767SAnurag.Maskey@Sun.COM 
4811767SAnurag.Maskey@Sun.COM static sysevent_handle_t *sysevent_handle;
4911767SAnurag.Maskey@Sun.COM 
5011767SAnurag.Maskey@Sun.COM /*
5111767SAnurag.Maskey@Sun.COM  * At present, we only handle EC_DEV_ADD/EC_DEV_REMOVE sysevents of
5211767SAnurag.Maskey@Sun.COM  * subclass ESC_NETWORK.  These signify hotplug addition/removal.
5311767SAnurag.Maskey@Sun.COM  * For EC_DEV_ADD, we:
5411767SAnurag.Maskey@Sun.COM  *      - extract the driver/instance sysevent attributes
5511767SAnurag.Maskey@Sun.COM  *      - combine these to get interface name and create associated NCUs
5611767SAnurag.Maskey@Sun.COM  *      at the link/IP level if required
5711767SAnurag.Maskey@Sun.COM  *      - enable those instances
5811767SAnurag.Maskey@Sun.COM  * For EC_DEV_REMOVE, we:
5911767SAnurag.Maskey@Sun.COM  *      - disable the associated link/IP NCUs
6011767SAnurag.Maskey@Sun.COM  */
6111767SAnurag.Maskey@Sun.COM static void
sysevent_handler(sysevent_t * ev)6211767SAnurag.Maskey@Sun.COM sysevent_handler(sysevent_t *ev)
6311767SAnurag.Maskey@Sun.COM {
6411767SAnurag.Maskey@Sun.COM 	int32_t instance;
6511767SAnurag.Maskey@Sun.COM 	char *driver;
6611767SAnurag.Maskey@Sun.COM 	char if_name[LIFNAMSIZ];
6711767SAnurag.Maskey@Sun.COM 	boolean_t link_added;
6811767SAnurag.Maskey@Sun.COM 	nvlist_t *attr_list;
6911767SAnurag.Maskey@Sun.COM 	char *event_class = sysevent_get_class_name(ev);
7011767SAnurag.Maskey@Sun.COM 	char *event_subclass = sysevent_get_subclass_name(ev);
7111767SAnurag.Maskey@Sun.COM 	nwamd_event_t link_event = NULL;
7211767SAnurag.Maskey@Sun.COM 
7311767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "sysevent_handler: event %s/%s", event_class,
7411767SAnurag.Maskey@Sun.COM 	    event_subclass);
7511767SAnurag.Maskey@Sun.COM 
7611767SAnurag.Maskey@Sun.COM 	/* Make sure sysevent is of expected class/subclass */
7711767SAnurag.Maskey@Sun.COM 	if ((strcmp(event_class, EC_DEV_ADD) != 0 &&
7811767SAnurag.Maskey@Sun.COM 	    strcmp(event_class, EC_DEV_REMOVE) != 0) ||
7911767SAnurag.Maskey@Sun.COM 	    strcmp(event_subclass, ESC_NETWORK) != 0) {
8011767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "sysevent_handler: unexpected sysevent "
8111767SAnurag.Maskey@Sun.COM 		    "class/subclass %s/%s", event_class, event_subclass);
8211767SAnurag.Maskey@Sun.COM 		return;
8311767SAnurag.Maskey@Sun.COM 	}
8411767SAnurag.Maskey@Sun.COM 
8511767SAnurag.Maskey@Sun.COM 	link_added = (strcmp(event_class, EC_DEV_ADD) == 0);
8611767SAnurag.Maskey@Sun.COM 
8711767SAnurag.Maskey@Sun.COM 	/*
8811767SAnurag.Maskey@Sun.COM 	 * Retrieve driver name and instance attributes, and combine to
8911767SAnurag.Maskey@Sun.COM 	 * get interface name.
9011767SAnurag.Maskey@Sun.COM 	 */
9111767SAnurag.Maskey@Sun.COM 	if (sysevent_get_attr_list(ev, &attr_list) != 0) {
9211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "sysevent_handler: sysevent_get_attr_list: %m");
9311767SAnurag.Maskey@Sun.COM 		return;
9411767SAnurag.Maskey@Sun.COM 	}
9511767SAnurag.Maskey@Sun.COM 	if (nvlist_lookup_string(attr_list, DEV_DRIVER_NAME, &driver) != 0 ||
9611767SAnurag.Maskey@Sun.COM 	    nvlist_lookup_int32(attr_list, DEV_INSTANCE, &instance) != 0) {
9711767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "sysevent_handler: nvlist_lookup "
9811767SAnurag.Maskey@Sun.COM 		    "of attributes failed: %m");
9911767SAnurag.Maskey@Sun.COM 		nvlist_free(attr_list);
10011767SAnurag.Maskey@Sun.COM 		return;
10111767SAnurag.Maskey@Sun.COM 	}
10211767SAnurag.Maskey@Sun.COM 	(void) snprintf(if_name, LIFNAMSIZ, "%s%d", driver, instance);
10311767SAnurag.Maskey@Sun.COM 	nvlist_free(attr_list);
10411767SAnurag.Maskey@Sun.COM 
10511767SAnurag.Maskey@Sun.COM 	/* Ignore sysevent events for other zones */
10611767SAnurag.Maskey@Sun.COM 	if (!nwamd_link_belongs_to_this_zone(if_name))
10711767SAnurag.Maskey@Sun.COM 		return;
10811767SAnurag.Maskey@Sun.COM 
10911767SAnurag.Maskey@Sun.COM 	/* Create event for link */
11011767SAnurag.Maskey@Sun.COM 	link_event = nwamd_event_init_link_action(if_name,
11111767SAnurag.Maskey@Sun.COM 	    link_added ? NWAM_ACTION_ADD : NWAM_ACTION_REMOVE);
11211767SAnurag.Maskey@Sun.COM 	if (link_event != NULL)
11311767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue(link_event);
11411767SAnurag.Maskey@Sun.COM }
11511767SAnurag.Maskey@Sun.COM 
11611767SAnurag.Maskey@Sun.COM /* ARGSUSED0 */
11711767SAnurag.Maskey@Sun.COM static void *
sysevent_initialization(void * arg)11811767SAnurag.Maskey@Sun.COM sysevent_initialization(void *arg)
11911767SAnurag.Maskey@Sun.COM {
12011767SAnurag.Maskey@Sun.COM 	const char *subclass = ESC_NETWORK;
12111767SAnurag.Maskey@Sun.COM 
12211767SAnurag.Maskey@Sun.COM 	do {
123*11918SMichael.Hunter@Sun.COM 		nwamd_escalate();
12411767SAnurag.Maskey@Sun.COM 		sysevent_handle = sysevent_bind_handle(sysevent_handler);
125*11918SMichael.Hunter@Sun.COM 		nwamd_deescalate();
12611767SAnurag.Maskey@Sun.COM 
12711767SAnurag.Maskey@Sun.COM 		(void) sleep(1);
12811767SAnurag.Maskey@Sun.COM 	} while (sysevent_handle == NULL);
12911767SAnurag.Maskey@Sun.COM 
13011767SAnurag.Maskey@Sun.COM 	/*
13111767SAnurag.Maskey@Sun.COM 	 * Subscribe to ESC_NETWORK subclass of EC_DEV_ADD and EC_DEV_REMOVE
13211767SAnurag.Maskey@Sun.COM 	 * events.  As a result,  we get sysevent notification of hotplug
13311767SAnurag.Maskey@Sun.COM 	 * add/remove events,  which we handle above in sysevent_handler().
13411767SAnurag.Maskey@Sun.COM 	 */
13511767SAnurag.Maskey@Sun.COM 	if (sysevent_subscribe_event(sysevent_handle, EC_DEV_ADD, &subclass, 1)
13611767SAnurag.Maskey@Sun.COM 	    != 0 ||
13711767SAnurag.Maskey@Sun.COM 	    sysevent_subscribe_event(sysevent_handle, EC_DEV_REMOVE, &subclass,
13811767SAnurag.Maskey@Sun.COM 	    1) != 0)
13911767SAnurag.Maskey@Sun.COM 		pfail("sysevent_subscribe_event: %s", strerror(errno));
14011767SAnurag.Maskey@Sun.COM 
14111767SAnurag.Maskey@Sun.COM 	return (NULL);
14211767SAnurag.Maskey@Sun.COM }
14311767SAnurag.Maskey@Sun.COM 
14411767SAnurag.Maskey@Sun.COM /*
14511767SAnurag.Maskey@Sun.COM  * We can't initialize in the main thread because we may need to wait until
14611767SAnurag.Maskey@Sun.COM  * svc:/system/sysevent:default finishes starting up.  So we create a thread to
14711767SAnurag.Maskey@Sun.COM  * initialize in.
14811767SAnurag.Maskey@Sun.COM  */
14911767SAnurag.Maskey@Sun.COM void
nwamd_sysevent_events_init(void)15011767SAnurag.Maskey@Sun.COM nwamd_sysevent_events_init(void)
15111767SAnurag.Maskey@Sun.COM {
15211767SAnurag.Maskey@Sun.COM 	int rc;
15311767SAnurag.Maskey@Sun.COM 	pthread_attr_t attr;
15411767SAnurag.Maskey@Sun.COM 
15511767SAnurag.Maskey@Sun.COM 	rc = pthread_attr_init(&attr);
15611767SAnurag.Maskey@Sun.COM 	if (rc != 0) {
15711767SAnurag.Maskey@Sun.COM 		pfail("nwamd_sysevents_init: pthread_attr_init failed: %s",
15811767SAnurag.Maskey@Sun.COM 		    strerror(rc));
15911767SAnurag.Maskey@Sun.COM 	}
16011767SAnurag.Maskey@Sun.COM 
16111767SAnurag.Maskey@Sun.COM 	rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
16211767SAnurag.Maskey@Sun.COM 	if (rc != 0) {
16311767SAnurag.Maskey@Sun.COM 		pfail("nwamd_sysevents_init: pthread_attr_setdetachstate "
16411767SAnurag.Maskey@Sun.COM 		    "failed: %s", strerror(rc));
16511767SAnurag.Maskey@Sun.COM 	}
16611767SAnurag.Maskey@Sun.COM 
16711767SAnurag.Maskey@Sun.COM 	rc = pthread_create(NULL, &attr, sysevent_initialization, NULL);
16811767SAnurag.Maskey@Sun.COM 	if (rc != 0) {
16911767SAnurag.Maskey@Sun.COM 		pfail("nwamd_sysevents_init: couldn't start sysevent init "
17011767SAnurag.Maskey@Sun.COM 		    "thread: %s", strerror(rc));
17111767SAnurag.Maskey@Sun.COM 	}
17211767SAnurag.Maskey@Sun.COM 
17311767SAnurag.Maskey@Sun.COM 	(void) pthread_attr_destroy(&attr);
17411767SAnurag.Maskey@Sun.COM }
17511767SAnurag.Maskey@Sun.COM 
17611767SAnurag.Maskey@Sun.COM void
nwamd_sysevent_events_fini(void)17711767SAnurag.Maskey@Sun.COM nwamd_sysevent_events_fini(void)
17811767SAnurag.Maskey@Sun.COM {
17911767SAnurag.Maskey@Sun.COM 	if (sysevent_handle != NULL) {
180*11918SMichael.Hunter@Sun.COM 		nwamd_escalate();
18111767SAnurag.Maskey@Sun.COM 		sysevent_unbind_handle(sysevent_handle);
182*11918SMichael.Hunter@Sun.COM 		nwamd_deescalate();
18311767SAnurag.Maskey@Sun.COM 	}
18411767SAnurag.Maskey@Sun.COM 	sysevent_handle = NULL;
18511767SAnurag.Maskey@Sun.COM }
186