16ba597c5SAnurag S. Maskey /* 26ba597c5SAnurag S. Maskey * CDDL HEADER START 36ba597c5SAnurag S. Maskey * 46ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the 56ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License"). 66ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License. 76ba597c5SAnurag S. Maskey * 86ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing. 106ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions 116ba597c5SAnurag S. Maskey * and limitations under the License. 126ba597c5SAnurag S. Maskey * 136ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each 146ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the 166ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying 176ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner] 186ba597c5SAnurag S. Maskey * 196ba597c5SAnurag S. Maskey * CDDL HEADER END 206ba597c5SAnurag S. Maskey */ 216ba597c5SAnurag S. Maskey 226ba597c5SAnurag S. Maskey /* 23*f6da83d4SAnurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 246ba597c5SAnurag S. Maskey */ 256ba597c5SAnurag S. Maskey 266ba597c5SAnurag S. Maskey #include <arpa/inet.h> 276ba597c5SAnurag S. Maskey #include <assert.h> 286ba597c5SAnurag S. Maskey #include <fcntl.h> 296ba597c5SAnurag S. Maskey #include <libdlpi.h> 306ba597c5SAnurag S. Maskey #include <libnwam.h> 316ba597c5SAnurag S. Maskey #include <net/if.h> 326ba597c5SAnurag S. Maskey #include <pthread.h> 336ba597c5SAnurag S. Maskey #include <stdio.h> 346ba597c5SAnurag S. Maskey #include <stdlib.h> 356ba597c5SAnurag S. Maskey #include <string.h> 366ba597c5SAnurag S. Maskey #include <sys/fcntl.h> 376ba597c5SAnurag S. Maskey #include <unistd.h> 386ba597c5SAnurag S. Maskey 396ba597c5SAnurag S. Maskey #include "events.h" 406ba597c5SAnurag S. Maskey #include "ncp.h" 416ba597c5SAnurag S. Maskey #include "ncu.h" 426ba597c5SAnurag S. Maskey #include "objects.h" 436ba597c5SAnurag S. Maskey #include "util.h" 446ba597c5SAnurag S. Maskey 456ba597c5SAnurag S. Maskey /* 466ba597c5SAnurag S. Maskey * dlpi_events.c - this file contains routines to retrieve 476ba597c5SAnurag S. Maskey * DL_NOTE_LINK_[UP|DOWN] events from the system and packages them for high 486ba597c5SAnurag S. Maskey * level processing. Holding a dlpi_handle to a link prevents the 496ba597c5SAnurag S. Maskey * associated driver unloading that can happen when IP is not plumbed, 506ba597c5SAnurag S. Maskey * so it is vital to ensure that the handle is open for the lifetime 516ba597c5SAnurag S. Maskey * of the WiFi connection. 526ba597c5SAnurag S. Maskey */ 536ba597c5SAnurag S. Maskey 546ba597c5SAnurag S. Maskey /* 556ba597c5SAnurag S. Maskey * This is a callback function executed when dlpi_recv() gets a DL_NOTE_LINK_UP. 566ba597c5SAnurag S. Maskey * It packages up the event for consumption by the link state machine. 576ba597c5SAnurag S. Maskey */ 586ba597c5SAnurag S. Maskey /* ARGSUSED0 */ 596ba597c5SAnurag S. Maskey static void 606ba597c5SAnurag S. Maskey nwamd_dlpi_notify(dlpi_handle_t dhp, dlpi_notifyinfo_t *info, void *arg) 616ba597c5SAnurag S. Maskey { 626ba597c5SAnurag S. Maskey nwamd_event_t ev; 636ba597c5SAnurag S. Maskey char *name = arg; 646ba597c5SAnurag S. Maskey 656ba597c5SAnurag S. Maskey if (info->dni_note & DL_NOTE_LINK_UP) 666ba597c5SAnurag S. Maskey ev = nwamd_event_init_link_state(name, B_TRUE); 676ba597c5SAnurag S. Maskey else 686ba597c5SAnurag S. Maskey ev = nwamd_event_init_link_state(name, B_FALSE); 696ba597c5SAnurag S. Maskey if (ev != NULL) 706ba597c5SAnurag S. Maskey nwamd_event_enqueue(ev); 716ba597c5SAnurag S. Maskey } 726ba597c5SAnurag S. Maskey 736ba597c5SAnurag S. Maskey /* 746ba597c5SAnurag S. Maskey * We are only intested in DL_NOTE_LINK_UP events which we've registered for 756ba597c5SAnurag S. Maskey * in nwamd_dlpi_add_link(). But we have to keep calling dlpi_recv() to 766ba597c5SAnurag S. Maskey * force the notification callback to be executed. 776ba597c5SAnurag S. Maskey */ 786ba597c5SAnurag S. Maskey static void * 796ba597c5SAnurag S. Maskey nwamd_dlpi_thread(void *arg) 806ba597c5SAnurag S. Maskey { 816ba597c5SAnurag S. Maskey int rc; 826ba597c5SAnurag S. Maskey dlpi_handle_t *dh = arg; 836ba597c5SAnurag S. Maskey 846ba597c5SAnurag S. Maskey do { 856ba597c5SAnurag S. Maskey rc = dlpi_recv(*dh, NULL, NULL, NULL, NULL, -1, NULL); 866ba597c5SAnurag S. Maskey } while (rc == DLPI_SUCCESS); 876ba597c5SAnurag S. Maskey nlog(LOG_ERR, "dlpi_recv failed: %s", dlpi_strerror(rc)); 886ba597c5SAnurag S. Maskey return (NULL); 896ba597c5SAnurag S. Maskey } 906ba597c5SAnurag S. Maskey 916ba597c5SAnurag S. Maskey /* 926ba597c5SAnurag S. Maskey * This is called when we want to start receiving notifications from state 936ba597c5SAnurag S. Maskey * changes on a link. 946ba597c5SAnurag S. Maskey */ 956ba597c5SAnurag S. Maskey void 966ba597c5SAnurag S. Maskey nwamd_dlpi_add_link(nwamd_object_t obj) 976ba597c5SAnurag S. Maskey { 986ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = obj->nwamd_object_data; 996ba597c5SAnurag S. Maskey nwamd_link_t *link; 1006ba597c5SAnurag S. Maskey dlpi_notifyid_t id; 1016ba597c5SAnurag S. Maskey int rc; 1026ba597c5SAnurag S. Maskey 1036ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_dlpi_add_link: ncu %p (%s) type %d", 1046ba597c5SAnurag S. Maskey ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1); 1056ba597c5SAnurag S. Maskey 1066ba597c5SAnurag S. Maskey assert(ncu != NULL && ncu->ncu_type == NWAM_NCU_TYPE_LINK); 1076ba597c5SAnurag S. Maskey 108*f6da83d4SAnurag S. Maskey link = &ncu->ncu_link; 1096ba597c5SAnurag S. Maskey 1106ba597c5SAnurag S. Maskey /* Already running? */ 1116ba597c5SAnurag S. Maskey if (link->nwamd_link_dlpi_thread != 0) { 1126ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_dlpi_add_link(%s) already running", 1136ba597c5SAnurag S. Maskey obj->nwamd_object_name); 1146ba597c5SAnurag S. Maskey return; 1156ba597c5SAnurag S. Maskey } 1166ba597c5SAnurag S. Maskey 1176ba597c5SAnurag S. Maskey rc = dlpi_open(ncu->ncu_name, &link->nwamd_link_dhp, 0); 1186ba597c5SAnurag S. Maskey if (rc != DLPI_SUCCESS) { 1196ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_dlpi_add_link: dlpi_open(%s) = %s", 1206ba597c5SAnurag S. Maskey ncu->ncu_name, dlpi_strerror(rc)); 1216ba597c5SAnurag S. Maskey return; 1226ba597c5SAnurag S. Maskey } 1236ba597c5SAnurag S. Maskey 1246ba597c5SAnurag S. Maskey nwamd_set_unset_link_properties(ncu, B_TRUE); 1256ba597c5SAnurag S. Maskey 1266ba597c5SAnurag S. Maskey rc = dlpi_enabnotify(link->nwamd_link_dhp, 1276ba597c5SAnurag S. Maskey DL_NOTE_LINK_UP | DL_NOTE_LINK_DOWN, nwamd_dlpi_notify, 1286ba597c5SAnurag S. Maskey ncu->ncu_name, &id); 1296ba597c5SAnurag S. Maskey if (rc != DLPI_SUCCESS) { 1306ba597c5SAnurag S. Maskey nlog(LOG_ERR, 1316ba597c5SAnurag S. Maskey "nwamd_dlpi_add_link: dlpi_enabnotify(%s) = %s", 1326ba597c5SAnurag S. Maskey obj->nwamd_object_name, dlpi_strerror(rc)); 1336ba597c5SAnurag S. Maskey dlpi_close(link->nwamd_link_dhp); 1346ba597c5SAnurag S. Maskey return; 1356ba597c5SAnurag S. Maskey } 1366ba597c5SAnurag S. Maskey 1376ba597c5SAnurag S. Maskey rc = pthread_create(&link->nwamd_link_dlpi_thread, NULL, 1386ba597c5SAnurag S. Maskey nwamd_dlpi_thread, &link->nwamd_link_dhp); 1396ba597c5SAnurag S. Maskey if (rc != 0) { 1406ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_dlpi_add_link: couldn't create " 1416ba597c5SAnurag S. Maskey "dlpi thread for %s: %s", obj->nwamd_object_name, 1426ba597c5SAnurag S. Maskey strerror(rc)); 1436ba597c5SAnurag S. Maskey dlpi_close(link->nwamd_link_dhp); 1446ba597c5SAnurag S. Maskey } 1456ba597c5SAnurag S. Maskey } 1466ba597c5SAnurag S. Maskey 1476ba597c5SAnurag S. Maskey /* 1486ba597c5SAnurag S. Maskey * This function is called when we are no longer interested in receiving 1496ba597c5SAnurag S. Maskey * notification from state changes on a link. 1506ba597c5SAnurag S. Maskey */ 1516ba597c5SAnurag S. Maskey void 1526ba597c5SAnurag S. Maskey nwamd_dlpi_delete_link(nwamd_object_t obj) 1536ba597c5SAnurag S. Maskey { 1546ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu = obj->nwamd_object_data; 1556ba597c5SAnurag S. Maskey 1566ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "nwamd_dlpi_delete_link: ncu %p (%s) type %d", 1576ba597c5SAnurag S. Maskey ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1); 1586ba597c5SAnurag S. Maskey 159*f6da83d4SAnurag S. Maskey if (ncu->ncu_link.nwamd_link_dlpi_thread != 0) { 1606ba597c5SAnurag S. Maskey (void) pthread_cancel( 161*f6da83d4SAnurag S. Maskey ncu->ncu_link.nwamd_link_dlpi_thread); 162*f6da83d4SAnurag S. Maskey (void) pthread_join(ncu->ncu_link.nwamd_link_dlpi_thread, NULL); 163*f6da83d4SAnurag S. Maskey ncu->ncu_link.nwamd_link_dlpi_thread = 0; 1646ba597c5SAnurag S. Maskey /* Unset properties before closing */ 1656ba597c5SAnurag S. Maskey nwamd_set_unset_link_properties(ncu, B_FALSE); 1666ba597c5SAnurag S. Maskey } 1676ba597c5SAnurag S. Maskey 168*f6da83d4SAnurag S. Maskey dlpi_close(ncu->ncu_link.nwamd_link_dhp); 169*f6da83d4SAnurag S. Maskey ncu->ncu_link.nwamd_link_dhp = NULL; 1706ba597c5SAnurag S. Maskey } 171