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