4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <arpa/inet.h>
36 #include <sys/fcntl.h>
46 * dlpi_events.c - this file contains routines to retrieve
47 * DL_NOTE_LINK_[UP|DOWN] events from the system and packages them for high
48 * level processing. Holding a dlpi_handle to a link prevents the
49 * associated driver unloading that can happen when IP is not plumbed,
50 * so it is vital to ensure that the handle is open for the lifetime
51 * of the WiFi connection.
55 * This is a callback function executed when dlpi_recv() gets a DL_NOTE_LINK_UP.
56 * It packages up the event for consumption by the link state machine.
60 nwamd_dlpi_notify(dlpi_handle_t dhp
, dlpi_notifyinfo_t
*info
, void *arg
)
65 if (info
->dni_note
& DL_NOTE_LINK_UP
)
66 ev
= nwamd_event_init_link_state(name
, B_TRUE
);
68 ev
= nwamd_event_init_link_state(name
, B_FALSE
);
70 nwamd_event_enqueue(ev
);
74 * We are only intested in DL_NOTE_LINK_UP events which we've registered for
75 * in nwamd_dlpi_add_link(). But we have to keep calling dlpi_recv() to
76 * force the notification callback to be executed.
79 nwamd_dlpi_thread(void *arg
)
82 dlpi_handle_t
*dh
= arg
;
85 rc
= dlpi_recv(*dh
, NULL
, NULL
, NULL
, NULL
, -1, NULL
);
86 } while (rc
== DLPI_SUCCESS
);
87 nlog(LOG_ERR
, "dlpi_recv failed: %s", dlpi_strerror(rc
));
92 * This is called when we want to start receiving notifications from state
96 nwamd_dlpi_add_link(nwamd_object_t obj
)
98 nwamd_ncu_t
*ncu
= obj
->nwamd_object_data
;
103 nlog(LOG_DEBUG
, "nwamd_dlpi_add_link: ncu %p (%s) type %d",
104 ncu
, obj
->nwamd_object_name
, ncu
!= NULL
? ncu
->ncu_type
: -1);
106 assert(ncu
!= NULL
&& ncu
->ncu_type
== NWAM_NCU_TYPE_LINK
);
108 link
= &ncu
->ncu_link
;
110 /* Already running? */
111 if (link
->nwamd_link_dlpi_thread
!= 0) {
112 nlog(LOG_DEBUG
, "nwamd_dlpi_add_link(%s) already running",
113 obj
->nwamd_object_name
);
117 rc
= dlpi_open(ncu
->ncu_name
, &link
->nwamd_link_dhp
, 0);
118 if (rc
!= DLPI_SUCCESS
) {
119 nlog(LOG_ERR
, "nwamd_dlpi_add_link: dlpi_open(%s) = %s",
120 ncu
->ncu_name
, dlpi_strerror(rc
));
124 nwamd_set_unset_link_properties(ncu
, B_TRUE
);
126 rc
= dlpi_enabnotify(link
->nwamd_link_dhp
,
127 DL_NOTE_LINK_UP
| DL_NOTE_LINK_DOWN
, nwamd_dlpi_notify
,
129 if (rc
!= DLPI_SUCCESS
) {
131 "nwamd_dlpi_add_link: dlpi_enabnotify(%s) = %s",
132 obj
->nwamd_object_name
, dlpi_strerror(rc
));
133 dlpi_close(link
->nwamd_link_dhp
);
137 rc
= pthread_create(&link
->nwamd_link_dlpi_thread
, NULL
,
138 nwamd_dlpi_thread
, &link
->nwamd_link_dhp
);
140 nlog(LOG_ERR
, "nwamd_dlpi_add_link: couldn't create "
141 "dlpi thread for %s: %s", obj
->nwamd_object_name
,
143 dlpi_close(link
->nwamd_link_dhp
);
148 * This function is called when we are no longer interested in receiving
149 * notification from state changes on a link.
152 nwamd_dlpi_delete_link(nwamd_object_t obj
)
154 nwamd_ncu_t
*ncu
= obj
->nwamd_object_data
;
156 nlog(LOG_DEBUG
, "nwamd_dlpi_delete_link: ncu %p (%s) type %d",
157 ncu
, obj
->nwamd_object_name
, ncu
!= NULL
? ncu
->ncu_type
: -1);
159 if (ncu
->ncu_link
.nwamd_link_dlpi_thread
!= 0) {
160 (void) pthread_cancel(
161 ncu
->ncu_link
.nwamd_link_dlpi_thread
);
162 (void) pthread_join(ncu
->ncu_link
.nwamd_link_dlpi_thread
, NULL
);
163 ncu
->ncu_link
.nwamd_link_dlpi_thread
= 0;
164 /* Unset properties before closing */
165 nwamd_set_unset_link_properties(ncu
, B_FALSE
);
168 dlpi_close(ncu
->ncu_link
.nwamd_link_dhp
);
169 ncu
->ncu_link
.nwamd_link_dhp
= NULL
;