Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c
+++ new/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
24 25 */
25 26
26 27 #include <arpa/inet.h>
27 28 #include <assert.h>
28 29 #include <libdlaggr.h>
29 30 #include <libdllink.h>
30 31 #include <libdlstat.h>
31 32 #include <libnwam.h>
32 33 #include <libscf.h>
33 34 #include <netinet/in.h>
34 35 #include <stdlib.h>
35 36 #include <strings.h>
37 +#include <sys/param.h>
36 38 #include <sys/socket.h>
37 39 #include <sys/time.h>
38 40 #include <sys/types.h>
39 41 #include <values.h>
40 42 #include <zone.h>
41 43
42 44 #include "conditions.h"
43 45 #include "events.h"
44 46 #include "objects.h"
45 47 #include "ncp.h"
46 48 #include "util.h"
47 49
48 50 /*
49 51 * ncu.c - handles various NCU tasks - intialization/refresh, state machine
50 52 * for NCUs etc.
51 53 */
52 54
53 55 #define VBOX_IFACE_PREFIX "vboxnet"
54 56
55 57 static void populate_ip_ncu_properties(nwam_ncu_handle_t, nwamd_ncu_t *);
56 58
57 59 /*
58 60 * Find ncu of specified type for link/interface name.
59 61 */
60 62 nwamd_object_t
61 63 nwamd_ncu_object_find(nwam_ncu_type_t type, const char *name)
62 64 {
63 65 nwam_error_t err;
64 66 char *object_name;
65 67 nwamd_object_t ncu_obj = NULL;
66 68
67 69 if ((err = nwam_ncu_name_to_typed_name(name, type, &object_name))
68 70 != NWAM_SUCCESS) {
69 71 nlog(LOG_ERR, "nwamd_ncu_find: nwam_ncu_name_to_typed_name "
70 72 "returned %s", nwam_strerror(err));
71 73 return (NULL);
72 74 }
73 75 ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name);
74 76
75 77 free(object_name);
76 78 return (ncu_obj);
77 79 }
78 80
79 81 nwam_error_t
80 82 nwamd_set_ncu_string(nwam_ncu_handle_t ncuh, char **strval, uint_t cnt,
81 83 const char *prop)
82 84 {
83 85 nwam_error_t err;
84 86 nwam_value_t val;
85 87
86 88 if ((err = nwam_value_create_string_array(strval, cnt, &val))
87 89 != NWAM_SUCCESS)
88 90 return (err);
89 91 err = nwam_ncu_set_prop_value(ncuh, prop, val);
90 92 nwam_value_free(val);
91 93 return (err);
92 94 }
93 95
94 96 nwam_error_t
95 97 nwamd_set_ncu_uint(nwam_ncu_handle_t ncuh, uint64_t *uintval, uint_t cnt,
96 98 const char *prop)
97 99 {
98 100 nwam_error_t err;
99 101 nwam_value_t val;
100 102
101 103 if ((err = nwam_value_create_uint64_array(uintval, cnt, &val))
102 104 != NWAM_SUCCESS)
103 105 return (err);
104 106 err = nwam_ncu_set_prop_value(ncuh, prop, val);
105 107 nwam_value_free(val);
106 108 return (err);
107 109 }
108 110
109 111 nwam_error_t
110 112 nwamd_get_ncu_string(nwam_ncu_handle_t ncuh, nwam_value_t *val, char ***strval,
111 113 uint_t *cnt, const char *prop)
112 114 {
113 115 nwam_error_t err;
114 116
115 117 if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
116 118 return (err);
117 119 return (nwam_value_get_string_array(*val, strval, cnt));
118 120 }
119 121
120 122 nwam_error_t
|
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
121 123 nwamd_get_ncu_uint(nwam_ncu_handle_t ncuh, nwam_value_t *val,
122 124 uint64_t **uintval, uint_t *cnt, const char *prop)
123 125 {
124 126 nwam_error_t err;
125 127
126 128 if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
127 129 return (err);
128 130 return (nwam_value_get_uint64_array(*val, uintval, cnt));
129 131 }
130 132
133 +nwam_error_t
134 +nwamd_get_ncu_boolean(nwam_ncu_handle_t ncuh, nwam_value_t *val,
135 + boolean_t **boolval, uint_t *cnt, const char *prop)
136 +{
137 + nwam_error_t err;
138 +
139 + if ((err = nwam_ncu_get_prop_value(ncuh, prop, val)) != NWAM_SUCCESS)
140 + return (err);
141 + return (nwam_value_get_boolean_array(*val, boolval, cnt));
142 +}
143 +
131 144 /*
132 145 * Run link/interface state machine in response to a state change
133 146 * or enable/disable action event.
134 147 */
135 148 static void
136 149 nwamd_ncu_state_machine(const char *object_name)
137 150 {
138 151 nwamd_object_t object;
139 152 nwamd_ncu_t *ncu;
140 153 link_state_t link_state;
141 154 nwamd_event_t event;
142 155 nwam_wlan_t key_wlan, connected_wlan;
143 156 nwamd_link_t *link;
144 157 char linkname[NWAM_MAX_NAME_LEN];
145 158 boolean_t up;
146 159
147 160 if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, object_name))
148 161 == NULL) {
149 162 nlog(LOG_ERR, "nwamd_ncu_state_machine: "
150 163 "request for nonexistent NCU %s", object_name);
151 164 return;
152 165 }
153 166
154 167 ncu = object->nwamd_object_data;
155 168 link = &ncu->ncu_link;
156 169
157 170 switch (object->nwamd_object_aux_state) {
158 171 case NWAM_AUX_STATE_INITIALIZED:
159 172 if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
160 173 /*
161 174 * For wired/wireless links, need to get link
162 175 * up/down events and even if these are not supported,
163 176 * dlpi_open()ing the link prevents the driver from
164 177 * being unloaded.
165 178 */
166 179 nwamd_dlpi_add_link(object);
167 180
168 181 if (link->nwamd_link_media == DL_WIFI) {
169 182 /*
170 183 * First, if we're unexpectedly connected,
171 184 * disconnect.
172 185 */
173 186 if (!link->nwamd_link_wifi_connected &&
174 187 nwamd_wlan_connected(object)) {
175 188 nlog(LOG_DEBUG,
176 189 "nwamd_ncu_state_machine: "
177 190 "WiFi unexpectedly connected, "
178 191 "disconnecting...");
179 192 (void) dladm_wlan_disconnect(dld_handle,
180 193 link->nwamd_link_id);
181 194 nwamd_set_selected_connected(ncu,
182 195 B_FALSE, B_FALSE);
183 196 }
184 197 /* move to scanning aux state */
185 198 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
186 199 object_name, object->nwamd_object_state,
187 200 NWAM_AUX_STATE_LINK_WIFI_SCANNING);
188 201 } else {
189 202 /*
190 203 * If initial wired link state is unknown, we
191 204 * will need to assume the link is up, since
192 205 * we won´t get DL_NOTE_LINK_UP/DOWN events.
193 206 */
194 207 link_state = nwamd_get_link_state
195 208 (ncu->ncu_name);
196 209 if (link_state == LINK_STATE_UP ||
197 210 link_state == LINK_STATE_UNKNOWN) {
198 211 nwamd_object_set_state
199 212 (NWAM_OBJECT_TYPE_NCU,
200 213 object_name, NWAM_STATE_ONLINE,
201 214 NWAM_AUX_STATE_UP);
202 215 } else {
203 216 nwamd_object_set_state
204 217 (NWAM_OBJECT_TYPE_NCU,
205 218 object_name,
206 219 NWAM_STATE_ONLINE_TO_OFFLINE,
207 220 NWAM_AUX_STATE_DOWN);
208 221 }
209 222 }
210 223 } else {
211 224 /*
212 225 * In the current implementation, initialization has to
213 226 * start from scratch since the complexity of minimizing
214 227 * configuration change is considerable (e.g. if we
215 228 * refresh and had DHCP running on the physical
216 229 * interface, and now have changed to static assignment,
217 230 * we need to remove DHCP etc). To avoid all this,
218 231 * unplumb before re-plumbing the protocols and
219 232 * addresses we wish to configure. In the future, it
220 233 * would be good to try and minimize configuration
221 234 * changes.
222 235 */
223 236 nwamd_unplumb_interface(ncu, AF_INET);
224 237 nwamd_unplumb_interface(ncu, AF_INET6);
225 238
226 239 /*
227 240 * We may be restarting the state machine. Re-read
228 241 * the IP NCU properties as the ipadm_addrobj_t in
229 242 * nwamd_if_address should not be reused.
230 243 */
231 244 populate_ip_ncu_properties(object->nwamd_object_handle,
232 245 ncu);
233 246
234 247 /*
235 248 * Enqueue a WAITING_FOR_ADDR aux state change so that
236 249 * we are eligible to receive the IF_STATE events
237 250 * associated with static, DHCP, DHCPv6 and autoconf
238 251 * address assignment. The latter two can happen
239 252 * quite quickly after plumbing so we need to be ready.
240 253 */
241 254 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
242 255 object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
243 256 NWAM_AUX_STATE_IF_WAITING_FOR_ADDR);
244 257
245 258 if (ncu->ncu_if.nwamd_if_ipv4)
246 259 nwamd_plumb_interface(ncu, AF_INET);
247 260
248 261 if (ncu->ncu_if.nwamd_if_ipv6)
249 262 nwamd_plumb_interface(ncu, AF_INET6);
250 263
251 264 /* Configure addresses */
252 265 nwamd_configure_interface_addresses(ncu);
253 266 }
254 267 break;
255 268
256 269 case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT:
257 270 case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR:
258 271 /*
259 272 * nothing to do here - RTM_NEWADDRs will trigger IF_STATE
260 273 * events to move us online.
261 274 */
262 275 break;
263 276
264 277 case NWAM_AUX_STATE_LINK_WIFI_SCANNING:
265 278 /* launch scan thread */
266 279 (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
267 280 (void) nwamd_wlan_scan(linkname);
268 281 /* Create periodic scan event */
269 282 nwamd_ncu_create_periodic_scan_event(object);
270 283 break;
271 284
272 285 case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION:
273 286 /* send "need choice" event */
274 287 event = nwamd_event_init_wlan
275 288 (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_CHOICE, B_FALSE,
276 289 link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr,
277 290 link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num);
278 291 if (event == NULL)
279 292 break;
280 293 nwamd_event_enqueue(event);
281 294 nwamd_set_selected_connected(ncu, B_FALSE, B_FALSE);
282 295 break;
283 296
284 297 case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY:
285 298 /*
286 299 * Send "need key" event. Set selected to true, connected
287 300 * and have_key to false. Do not fill in WLAN details as
288 301 * multiple WLANs may match the ESSID name, and each may
289 302 * have a different speed and channel.
290 303 */
291 304 bzero(&key_wlan, sizeof (key_wlan));
292 305 (void) strlcpy(key_wlan.nww_essid, link->nwamd_link_wifi_essid,
293 306 sizeof (key_wlan.nww_essid));
294 307 (void) strlcpy(key_wlan.nww_bssid, link->nwamd_link_wifi_bssid,
295 308 sizeof (key_wlan.nww_bssid));
296 309 key_wlan.nww_security_mode =
297 310 link->nwamd_link_wifi_security_mode;
298 311 key_wlan.nww_selected = B_TRUE;
299 312 key_wlan.nww_connected = B_FALSE;
300 313 key_wlan.nww_have_key = B_FALSE;
301 314 event = nwamd_event_init_wlan
302 315 (ncu->ncu_name, NWAM_EVENT_TYPE_WLAN_NEED_KEY, B_FALSE,
303 316 &key_wlan, 1);
304 317 if (event == NULL)
305 318 break;
306 319 nwamd_event_enqueue(event);
307 320 break;
308 321
309 322 case NWAM_AUX_STATE_LINK_WIFI_CONNECTING:
310 323 (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
311 324 nwamd_wlan_connect(linkname);
312 325 break;
313 326
314 327 case NWAM_AUX_STATE_UP:
315 328 case NWAM_AUX_STATE_DOWN:
316 329 up = (object->nwamd_object_aux_state == NWAM_AUX_STATE_UP);
317 330 if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
318 331 if (link->nwamd_link_media == DL_WIFI) {
319 332 /*
320 333 * Connected/disconnected - send WLAN
321 334 * connection report.
322 335 */
323 336 link->nwamd_link_wifi_connected = up;
324 337 nwamd_set_selected_connected(ncu, B_TRUE, up);
325 338
326 339 (void) strlcpy(connected_wlan.nww_essid,
327 340 link->nwamd_link_wifi_essid,
328 341 sizeof (connected_wlan.nww_essid));
329 342 (void) strlcpy(connected_wlan.nww_bssid,
330 343 link->nwamd_link_wifi_bssid,
331 344 sizeof (connected_wlan.nww_bssid));
332 345 connected_wlan.nww_security_mode =
333 346 link->nwamd_link_wifi_security_mode;
334 347 event = nwamd_event_init_wlan
335 348 (ncu->ncu_name,
336 349 NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT, up,
337 350 &connected_wlan, 1);
338 351 if (event == NULL)
339 352 break;
340 353 nwamd_event_enqueue(event);
341 354
342 355 /*
343 356 * If disconnected, restart the state machine
344 357 * for the WiFi link (WiFi is always trying
345 358 * to connect).
346 359 *
347 360 * If connected, start signal strength
348 361 * monitoring thread.
349 362 */
350 363 if (!up && ncu->ncu_enabled) {
351 364 nlog(LOG_DEBUG,
352 365 "nwamd_ncu_state_machine: "
353 366 "wifi disconnect - start over "
354 367 "after %dsec interval",
355 368 WIRELESS_RETRY_INTERVAL);
356 369 link->nwamd_link_wifi_connected =
357 370 B_FALSE;
358 371 /* propogate down event to IP NCU */
359 372 nwamd_propogate_link_up_down_to_ip
360 373 (ncu->ncu_name, B_FALSE);
361 374 nwamd_object_set_state_timed
362 375 (NWAM_OBJECT_TYPE_NCU, object_name,
363 376 NWAM_STATE_OFFLINE_TO_ONLINE,
364 377 NWAM_AUX_STATE_INITIALIZED,
365 378 WIRELESS_RETRY_INTERVAL);
366 379 } else {
367 380 nlog(LOG_DEBUG,
368 381 "nwamd_ncu_state_machine: "
369 382 "wifi connected, start monitoring");
370 383 (void) strlcpy(linkname, ncu->ncu_name,
371 384 sizeof (linkname));
372 385 nwamd_wlan_monitor_signal(linkname);
373 386 }
374 387 }
375 388 }
376 389
377 390 /* If not in ONLINE/OFFLINE state yet, change state */
378 391 if ((up && object->nwamd_object_state != NWAM_STATE_ONLINE) ||
379 392 (!up && object->nwamd_object_state != NWAM_STATE_OFFLINE)) {
380 393 nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
381 394 "%s is moving %s", object_name,
382 395 up ? "online" : "offline");
383 396 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
384 397 object_name,
385 398 up ? NWAM_STATE_ONLINE : NWAM_STATE_OFFLINE,
386 399 up ? NWAM_AUX_STATE_UP : NWAM_AUX_STATE_DOWN);
387 400
388 401 if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
389 402 if (up) {
390 403 /*
391 404 * Moving online, add v4/v6 default
392 405 * routes (if any).
393 406 */
394 407 nwamd_add_default_routes(ncu);
395 408 } else {
396 409 /*
397 410 * If this is an interface NCU and we
398 411 * got a down event, it is a consequence
399 412 * of NCU refresh, so reapply addresses
400 413 * by reinitializing.
401 414 */
402 415 nwamd_object_set_state
403 416 (NWAM_OBJECT_TYPE_NCU, object_name,
404 417 NWAM_STATE_OFFLINE_TO_ONLINE,
405 418 NWAM_AUX_STATE_INITIALIZED);
406 419 }
407 420 }
408 421 } else {
409 422 nlog(LOG_DEBUG, "nwamd_ncu_state_machine: "
410 423 "%s is %s", object_name,
411 424 up ? "online" : "offline");
412 425 }
413 426 /*
414 427 * NCU is UP or DOWN, trigger all condition checking, even if
415 428 * the NCU is already in the ONLINE state - an ENM may depend
416 429 * on NCU activity.
417 430 */
418 431 nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS);
419 432 break;
420 433
421 434 case NWAM_AUX_STATE_CONDITIONS_NOT_MET:
422 435 /*
423 436 * Link/interface is moving offline. Nothing to do except
424 437 * for WiFi, where we disconnect. Don't unplumb IP on
425 438 * a link since it may be a transient change.
426 439 */
427 440 if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
428 441 if (link->nwamd_link_media == DL_WIFI) {
429 442 (void) dladm_wlan_disconnect(dld_handle,
430 443 link->nwamd_link_id);
431 444 link->nwamd_link_wifi_connected = B_FALSE;
432 445 nwamd_set_selected_connected(ncu, B_FALSE,
433 446 B_FALSE);
434 447 }
435 448 } else {
436 449 /*
437 450 * Unplumb here. In the future we may elaborate on
438 451 * the approach used and not unplumb for WiFi
439 452 * until we reconnect to a different WLAN (i.e. with
440 453 * a different ESSID).
441 454 */
442 455 nwamd_unplumb_interface(ncu, AF_INET);
443 456 nwamd_unplumb_interface(ncu, AF_INET6);
444 457 }
445 458 if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
446 459 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
447 460 object_name, NWAM_STATE_OFFLINE,
448 461 NWAM_AUX_STATE_CONDITIONS_NOT_MET);
449 462 }
450 463 break;
451 464
452 465 case NWAM_AUX_STATE_MANUAL_DISABLE:
453 466 /* Manual disable, set enabled state appropriately. */
454 467 ncu->ncu_enabled = B_FALSE;
455 468 /* FALLTHROUGH */
456 469 case NWAM_AUX_STATE_UNINITIALIZED:
457 470 case NWAM_AUX_STATE_NOT_FOUND:
458 471 /*
459 472 * Link/interface NCU has been disabled/deactivated/removed.
460 473 * For WiFi links disconnect, and for IP interfaces we unplumb.
461 474 */
462 475 if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
463 476 if (link->nwamd_link_media == DL_WIFI) {
464 477 (void) dladm_wlan_disconnect(dld_handle,
465 478 link->nwamd_link_id);
466 479 link->nwamd_link_wifi_connected = B_FALSE;
467 480 nwamd_set_selected_connected(ncu, B_FALSE,
468 481 B_FALSE);
469 482 }
470 483 nwamd_dlpi_delete_link(object);
471 484 } else {
472 485 /* Unplumb here. */
473 486 if (ncu->ncu_if.nwamd_if_ipv4) {
474 487 nwamd_unplumb_interface(ncu, AF_INET);
475 488 }
476 489 if (ncu->ncu_if.nwamd_if_ipv6) {
477 490 nwamd_unplumb_interface(ncu, AF_INET6);
478 491 }
479 492 /* trigger location condition checking */
480 493 nwamd_create_triggered_condition_check_event(0);
481 494 }
482 495
483 496 switch (object->nwamd_object_aux_state) {
484 497 case NWAM_AUX_STATE_MANUAL_DISABLE:
485 498 /* Change state to DISABLED if manually disabled */
486 499 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
487 500 object_name, NWAM_STATE_DISABLED,
488 501 NWAM_AUX_STATE_MANUAL_DISABLE);
489 502 /* Note that NCU has been disabled */
490 503 ncu->ncu_enabled = B_FALSE;
491 504 break;
492 505 case NWAM_AUX_STATE_NOT_FOUND:
493 506 /* Change state to UNINITIALIZED for device removal */
494 507 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
495 508 object_name, NWAM_STATE_UNINITIALIZED,
496 509 NWAM_AUX_STATE_NOT_FOUND);
497 510 break;
498 511 default:
499 512 break;
500 513 }
501 514 break;
502 515 default:
503 516 nlog(LOG_ERR, "nwamd_ncu_state_machine: unexpected state");
504 517 break;
505 518 }
506 519
507 520 nwamd_object_release(object);
508 521 }
509 522
510 523 static int
511 524 ncu_create_init_fini_event(nwam_ncu_handle_t ncuh, void *data)
512 525 {
513 526 boolean_t *init = data;
514 527 char *name, *typedname;
515 528 nwam_error_t err;
516 529 nwam_value_t typeval = NULL;
517 530 uint64_t *type;
518 531 uint_t numvalues;
519 532 nwamd_event_t ncu_event;
520 533
521 534 if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
522 535 nlog(LOG_ERR,
523 536 "ncu_create_init_fini_event: could not get NCU name");
524 537 return (0);
525 538 }
526 539
527 540 nlog(LOG_DEBUG, "ncu_create_init_fini_event(%s, %p)", name, data);
528 541
529 542 if ((err = nwamd_get_ncu_uint(ncuh, &typeval, &type, &numvalues,
530 543 NWAM_NCU_PROP_TYPE)) != NWAM_SUCCESS) {
531 544 nlog(LOG_ERR, "ncu_create_init_fini_event: "
532 545 "could not get NCU type: %s", nwam_strerror(err));
533 546 free(name);
534 547 nwam_value_free(typeval);
535 548 return (0);
536 549 }
537 550
538 551 /* convert name to typedname for event */
539 552 if ((err = nwam_ncu_name_to_typed_name(name, *type, &typedname))
540 553 != NWAM_SUCCESS) {
541 554 nlog(LOG_ERR, "ncu_create_init_fini_event: "
542 555 "NCU name translation failed: %s", nwam_strerror(err));
543 556 free(name);
544 557 return (0);
545 558 }
546 559 free(name);
547 560 nwam_value_free(typeval);
548 561
549 562 ncu_event = nwamd_event_init(*init ?
550 563 NWAM_EVENT_TYPE_OBJECT_INIT : NWAM_EVENT_TYPE_OBJECT_FINI,
551 564 NWAM_OBJECT_TYPE_NCU, 0, typedname);
552 565 if (ncu_event != NULL)
553 566 nwamd_event_enqueue(ncu_event);
554 567 free(typedname);
555 568
556 569 return (0);
557 570 }
558 571
559 572 /*
560 573 * Initialization - walk the NCUs, creating initialization events for each
561 574 * NCU. nwamd_ncu_handle_init_event() will check if the associated
562 575 * physical link exists or not.
563 576 */
564 577 void
565 578 nwamd_init_ncus(void)
566 579 {
567 580 boolean_t init = B_TRUE;
568 581
569 582 (void) pthread_mutex_lock(&active_ncp_mutex);
570 583 if (active_ncph != NULL) {
571 584 nlog(LOG_DEBUG, "nwamd_init_ncus: "
572 585 "(re)intializing NCUs for NCP %s", active_ncp);
573 586 (void) nwam_ncp_walk_ncus(active_ncph,
574 587 ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
575 588 NULL);
576 589 }
577 590 (void) pthread_mutex_unlock(&active_ncp_mutex);
578 591 }
579 592
580 593 void
581 594 nwamd_fini_ncus(void)
582 595 {
583 596 boolean_t init = B_FALSE;
584 597
585 598 /* We may not have an active NCP on initialization, so skip fini */
586 599 (void) pthread_mutex_lock(&active_ncp_mutex);
587 600 if (active_ncph != NULL) {
588 601 nlog(LOG_DEBUG, "nwamd_fini_ncus: deinitializing NCUs for %s",
589 602 active_ncp);
590 603 (void) nwam_ncp_walk_ncus(active_ncph,
591 604 ncu_create_init_fini_event, &init, NWAM_FLAG_NCU_TYPE_ALL,
592 605 NULL);
593 606 }
594 607 (void) pthread_mutex_unlock(&active_ncp_mutex);
595 608 }
596 609
597 610 /*
598 611 * Most properties of this type don't need to be cached locally. Only those
599 612 * interesting to the daemon are stored in an nwamd_ncu_t.
600 613 */
601 614 static void
602 615 populate_common_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
603 616 {
604 617 nwam_value_t ncu_prop;
605 618 nwam_error_t err;
606 619 boolean_t enablevalue;
607 620 uint_t numvalues;
608 621 char **parent;
609 622
610 623 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
611 624 &ncu_prop)) != NWAM_SUCCESS) {
612 625 char *name;
613 626 (void) nwam_ncu_name_to_typed_name(ncu_data->ncu_name,
614 627 ncu_data->ncu_type, &name);
615 628 nlog(LOG_ERR, "nwam_ncu_get_prop_value %s ENABLED failed: %s",
616 629 name, nwam_strerror(err));
617 630 free(name);
618 631 ncu_data->ncu_enabled = B_TRUE;
619 632 } else {
620 633 if ((err = nwam_value_get_boolean(ncu_prop, &enablevalue)) !=
621 634 NWAM_SUCCESS) {
622 635 nlog(LOG_ERR, "nwam_value_get_boolean ENABLED failed: "
623 636 "%s", nwam_strerror(err));
624 637 } else {
625 638 ncu_data->ncu_enabled = enablevalue;
626 639 }
627 640 nwam_value_free(ncu_prop);
628 641 }
629 642
630 643 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &parent,
631 644 &numvalues, NWAM_NCU_PROP_PARENT_NCP)) != NWAM_SUCCESS) {
632 645 nlog(LOG_ERR, "nwam_ncu_get_prop_value %s PARENT failed: %s",
633 646 ncu_data->ncu_name, nwam_strerror(err));
634 647 } else {
635 648 (void) strlcpy(ncu_data->ncu_parent, parent[0],
636 649 sizeof (ncu_data->ncu_parent));
637 650 nwam_value_free(ncu_prop);
638 651 }
639 652 }
640 653
641 654 /*
642 655 * Read in link properties.
643 656 */
644 657 static void
645 658 populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
646 659 {
647 660 nwam_value_t ncu_prop;
648 661 nwam_error_t err;
649 662 char **mac_addr;
650 663 uint64_t *uintval;
651 664 uint_t numvalues;
652 665
653 666 /* activation-mode */
654 667 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
655 668 NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
656 669 nlog(LOG_ERR,
657 670 "populate_link_ncu_properties: could not get %s value: %s",
658 671 NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err));
659 672 } else {
660 673 ncu_data->ncu_link.nwamd_link_activation_mode = uintval[0];
661 674 nwam_value_free(ncu_prop);
662 675 }
663 676
664 677 /* priority-group and priority-mode for prioritized activation */
665 678 if (ncu_data->ncu_link.nwamd_link_activation_mode ==
666 679 NWAM_ACTIVATION_MODE_PRIORITIZED) {
667 680 /* ncus with prioritized activation are always enabled */
668 681 ncu_data->ncu_enabled = B_TRUE;
669 682 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
670 683 &numvalues, NWAM_NCU_PROP_PRIORITY_MODE))
671 684 != NWAM_SUCCESS) {
672 685 nlog(LOG_ERR, "populate_link_ncu_properties: "
673 686 "could not get %s value: %s",
674 687 NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err));
675 688 } else {
676 689 ncu_data->ncu_link.nwamd_link_priority_mode =
677 690 uintval[0];
678 691 nwam_value_free(ncu_prop);
679 692 }
680 693
681 694 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval,
682 695 &numvalues, NWAM_NCU_PROP_PRIORITY_GROUP))
683 696 != NWAM_SUCCESS) {
684 697 nlog(LOG_ERR, "populate_link_ncu_properties: "
685 698 "could not get %s value: %s",
686 699 NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err));
687 700 } else {
688 701 ncu_data->ncu_link.nwamd_link_priority_group =
689 702 uintval[0];
690 703 nwam_value_free(ncu_prop);
691 704 }
692 705 }
693 706
694 707 /* link-mac-addr */
695 708 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &mac_addr, &numvalues,
696 709 NWAM_NCU_PROP_LINK_MAC_ADDR)) != NWAM_SUCCESS) {
697 710 nlog(LOG_DEBUG,
698 711 "populate_link_ncu_properties: could not get %s value: %s",
699 712 NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err));
700 713 ncu_data->ncu_link.nwamd_link_mac_addr = NULL;
701 714 } else {
702 715 ncu_data->ncu_link.nwamd_link_mac_addr = strdup(*mac_addr);
703 716 ncu_data->ncu_link.nwamd_link_mac_addr_len = strlen(*mac_addr);
704 717 nwam_value_free(ncu_prop);
705 718 }
706 719
707 720 /* link-mtu */
708 721 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &uintval, &numvalues,
709 722 NWAM_NCU_PROP_LINK_MTU)) != NWAM_SUCCESS) {
710 723 nlog(LOG_DEBUG,
711 724 "populate_link_ncu_properties: could not get %s value: %s",
712 725 NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err));
713 726 ncu_data->ncu_link.nwamd_link_mtu = 0;
714 727 } else {
715 728 ncu_data->ncu_link.nwamd_link_mtu = uintval[0];
716 729 nwam_value_free(ncu_prop);
717 730 }
718 731
719 732 /* link-autopush */
720 733 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop,
721 734 &ncu_data->ncu_link.nwamd_link_autopush,
722 735 &ncu_data->ncu_link.nwamd_link_num_autopush,
723 736 NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) {
724 737 nlog(LOG_DEBUG,
725 738 "populate_link_ncu_properties: could not get %s value: %s",
|
↓ open down ↓ |
585 lines elided |
↑ open up ↑ |
726 739 NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err));
727 740 ncu_data->ncu_link.nwamd_link_num_autopush = 0;
728 741 }
729 742 }
730 743
731 744 static void
732 745 populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data)
733 746 {
734 747 nwamd_if_t *nif = &ncu_data->ncu_if;
735 748 struct nwamd_if_address **nifa, *nifai, *nifait;
736 - boolean_t static_addr = B_FALSE;
749 + boolean_t static_addr = B_FALSE, *boolvalue, dhcp_primary = B_FALSE;
737 750 uint64_t *addrsrcvalue;
738 751 nwam_value_t ncu_prop;
739 752 nwam_error_t err;
740 753 ipadm_addrobj_t ipaddr;
741 754 ipadm_status_t ipstatus;
742 - char **addrvalue;
755 + char **addrvalue, ipreqhost[MAXNAMELEN];
743 756 uint_t numvalues;
744 757 uint64_t *ipversion;
745 758 int i;
746 759
747 760 nif->nwamd_if_ipv4 = B_FALSE;
748 761 nif->nwamd_if_ipv6 = B_FALSE;
749 762 nif->nwamd_if_dhcp_requested = B_FALSE;
750 763 nif->nwamd_if_stateful_requested = B_FALSE;
751 764 nif->nwamd_if_stateless_requested = B_FALSE;
752 765 nif->nwamd_if_ipv4_default_route_set = B_FALSE;
753 766 nif->nwamd_if_ipv6_default_route_set = B_FALSE;
754 767
755 768 /* ip-version */
756 769 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &ipversion, &numvalues,
757 770 NWAM_NCU_PROP_IP_VERSION)) != NWAM_SUCCESS) {
758 771 nlog(LOG_ERR,
759 772 "populate_ip_ncu_properties: could not get %s value: %s",
760 773 NWAM_NCU_PROP_IP_VERSION, nwam_strerror(err));
761 774 } else {
762 775 for (i = 0; i < numvalues; i++) {
763 776 switch (ipversion[i]) {
764 777 case IPV4_VERSION:
765 778 nif->nwamd_if_ipv4 = B_TRUE;
766 779 break;
767 780 case IPV6_VERSION:
768 781 nif->nwamd_if_ipv6 = B_TRUE;
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
769 782 break;
770 783 default:
771 784 nlog(LOG_ERR, "bogus ip version %lld",
772 785 ipversion[i]);
773 786 break;
774 787 }
775 788 }
776 789 nwam_value_free(ncu_prop);
777 790 }
778 791
792 + /* ip-primary */
793 + if ((err = nwamd_get_ncu_boolean(ncuh, &ncu_prop, &boolvalue,
794 + &numvalues, NWAM_NCU_PROP_IP_PRIMARY)) != NWAM_SUCCESS) {
795 + /* ip-primary is optional, so do not LOG_ERR */
796 + nlog(LOG_DEBUG, "populate_ip_ncu_properties: "
797 + "could not get %s value: %s",
798 + NWAM_NCU_PROP_IP_PRIMARY, nwam_strerror(err));
799 + } else {
800 + if (numvalues > 0)
801 + dhcp_primary = boolvalue[0];
802 + nwam_value_free(ncu_prop);
803 + }
804 +
805 + /* ip-reqhost */
806 + *ipreqhost = '\0';
807 +
808 + if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
809 + &numvalues, NWAM_NCU_PROP_IP_REQHOST)) != NWAM_SUCCESS) {
810 + /* ip-reqhost is optional, so do not LOG_ERR */
811 + nlog(LOG_DEBUG, "populate_ip_ncu_properties: "
812 + "could not get %s value: %s",
813 + NWAM_NCU_PROP_IP_REQHOST, nwam_strerror(err));
814 + } else {
815 + if (numvalues > 0 && strlcpy(ipreqhost, addrvalue[0],
816 + sizeof (ipreqhost)) >= sizeof (ipreqhost)) {
817 + nlog(LOG_WARNING, "populate_ip_ncu_properties: "
818 + "too long %s value: %s",
819 + NWAM_NCU_PROP_IP_REQHOST, addrvalue[0]);
820 + *ipreqhost = '\0';
821 + }
822 + nwam_value_free(ncu_prop);
823 + }
824 +
779 825 /* Free the old list. */
780 826 for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) {
781 827 nifait = nifai->next;
782 828 nifai->next = NULL;
783 829 ipadm_destroy_addrobj(nifai->ipaddr);
784 830 free(nifai);
785 831 }
786 832 nif->nwamd_if_list = NULL;
787 833 nifa = &(nif->nwamd_if_list);
788 834
789 835 if (!nif->nwamd_if_ipv4)
790 836 goto skip_ipv4;
791 837
792 838 /* ipv4-addrsrc */
793 839 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
794 840 &numvalues, NWAM_NCU_PROP_IPV4_ADDRSRC)) != NWAM_SUCCESS) {
795 841 nlog(nif->nwamd_if_ipv4 ? LOG_ERR : LOG_DEBUG,
796 842 "populate_ip_ncu_properties: could not get %s value: %s",
797 843 NWAM_NCU_PROP_IPV4_ADDRSRC, nwam_strerror(err));
798 844 } else {
799 845 for (i = 0; i < numvalues; i++) {
800 846 switch (addrsrcvalue[i]) {
801 847 case NWAM_ADDRSRC_DHCP:
802 848 nif->nwamd_if_dhcp_requested = B_TRUE;
803 849 break;
804 850 case NWAM_ADDRSRC_STATIC:
805 851 static_addr = B_TRUE;
806 852 break;
807 853 default:
808 854 break;
809 855 }
810 856 }
811 857 nwam_value_free(ncu_prop);
812 858 }
813 859 if (nif->nwamd_if_dhcp_requested) {
814 860 ipstatus = ipadm_create_addrobj(IPADM_ADDR_DHCP,
815 861 ncu_data->ncu_name, &ipaddr);
816 862 if (ipstatus != IPADM_SUCCESS) {
817 863 nlog(LOG_ERR, "populate_ip_ncu_properties: "
818 864 "ipadm_create_addrobj failed for v4 dhcp: %s",
819 865 ipadm_status2str(ipstatus));
820 866 goto skip_ipv4_dhcp;
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
821 867 }
822 868
823 869 ipstatus = ipadm_set_wait_time(ipaddr, ncu_wait_time);
824 870 if (ipstatus != IPADM_SUCCESS) {
825 871 nlog(LOG_ERR, "populate_ip_ncu_properties: "
826 872 "ipadm_set_wait_time failed for v4 dhcp: %s",
827 873 ipadm_status2str(ipstatus));
828 874 ipadm_destroy_addrobj(ipaddr);
829 875 goto skip_ipv4_dhcp;
830 876 }
877 + ipstatus = ipadm_set_primary(ipaddr, dhcp_primary);
878 + if (ipstatus != IPADM_SUCCESS) {
879 + nlog(LOG_ERR, "populate_ip_ncu_properties: "
880 + "ipadm_set_primary failed for v4 dhcp: %s",
881 + ipadm_status2str(ipstatus));
882 + ipadm_destroy_addrobj(ipaddr);
883 + goto skip_ipv4_dhcp;
884 + }
885 + ipstatus = ipadm_set_reqhost(ipaddr, ipreqhost);
886 + if (ipstatus != IPADM_SUCCESS) {
887 + nlog(LOG_ERR, "populate_ip_ncu_properties: "
888 + "ipadm_set_reqhost failed for v4 dhcp: %s",
889 + ipadm_status2str(ipstatus));
890 + ipadm_destroy_addrobj(ipaddr);
891 + goto skip_ipv4_dhcp;
892 + }
831 893 if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
832 894 (*nifa)->family = AF_INET;
833 895 (*nifa)->ipaddr_atype = IPADM_ADDR_DHCP;
834 896 (*nifa)->ipaddr = ipaddr;
835 897 nifa = &((*nifa)->next);
836 898 *nifa = NULL;
837 899 } else {
838 900 nlog(LOG_ERR, "populate_ip_ncu_properties: "
839 901 "couldn't allocate nwamd address for v4 dhcp: %s",
840 902 strerror(errno));
841 903 ipadm_destroy_addrobj(ipaddr);
842 904 }
843 905 }
844 906
845 907 skip_ipv4_dhcp:
846 908 /* ipv4-addr */
847 909 if (static_addr) {
848 910 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
849 911 &numvalues, NWAM_NCU_PROP_IPV4_ADDR)) != NWAM_SUCCESS) {
850 912 nlog(LOG_ERR, "populate_ip_ncu_properties: "
851 - "could not get %s value; %s",
913 + "could not get %s value: %s",
852 914 NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err));
853 915 } else {
854 916 for (i = 0; i < numvalues; i++) {
855 917 ipstatus = ipadm_create_addrobj(
856 918 IPADM_ADDR_STATIC, ncu_data->ncu_name,
857 919 &ipaddr);
858 920 if (ipstatus != IPADM_SUCCESS) {
859 921 nlog(LOG_ERR,
860 922 "populate_ip_ncu_properties: "
861 923 "ipadm_create_addrobj failed "
862 924 "for %s: %s", addrvalue[i],
863 925 ipadm_status2str(ipstatus));
864 926 continue;
865 927 }
866 928 /* ipadm_set_addr takes <addr>[/<mask>] */
867 929 ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
868 930 AF_INET);
869 931 if (ipstatus != IPADM_SUCCESS) {
870 932 nlog(LOG_ERR,
871 933 "populate_ip_ncu_properties: "
872 934 "ipadm_set_addr failed for %s: %s",
873 935 addrvalue[i],
874 936 ipadm_status2str(ipstatus));
875 937 ipadm_destroy_addrobj(ipaddr);
876 938 continue;
877 939 }
878 940
879 941 if ((*nifa = calloc(sizeof (**nifa), 1))
880 942 != NULL) {
881 943 (*nifa)->family = AF_INET;
882 944 (*nifa)->ipaddr_atype =
883 945 IPADM_ADDR_STATIC;
884 946 (*nifa)->ipaddr = ipaddr;
885 947 nifa = &((*nifa)->next);
886 948 } else {
887 949 nlog(LOG_ERR,
888 950 "populate_ip_ncu_properties: "
889 951 "couldn't allocate nwamd address "
890 952 "for %s: %s", addrvalue[i],
891 953 strerror(errno));
892 954 ipadm_destroy_addrobj(ipaddr);
893 955 }
894 956 }
895 957 *nifa = NULL;
896 958
897 959 nwam_value_free(ncu_prop);
898 960 }
899 961 }
900 962
901 963 /* get default route, if any */
902 964 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
903 965 &numvalues, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
904 966 /* Only one default route is allowed. */
905 967 nif->nwamd_if_ipv4_default_route.sin_family = AF_INET;
906 968 (void) inet_pton(AF_INET, addrvalue[0],
907 969 &(nif->nwamd_if_ipv4_default_route.sin_addr));
908 970 nif->nwamd_if_ipv4_default_route_set = B_TRUE;
909 971 nwam_value_free(ncu_prop);
910 972 }
911 973
912 974 skip_ipv4:
913 975 if (!nif->nwamd_if_ipv6)
914 976 goto skip_ipv6;
915 977
916 978 /* ipv6-addrsrc */
917 979 static_addr = B_FALSE;
918 980 if ((err = nwamd_get_ncu_uint(ncuh, &ncu_prop, &addrsrcvalue,
919 981 &numvalues, NWAM_NCU_PROP_IPV6_ADDRSRC)) != NWAM_SUCCESS) {
920 982 nlog(nif->nwamd_if_ipv6 ? LOG_ERR : LOG_DEBUG,
921 983 "populate_ip_ncu_properties: could not get %s value: %s",
922 984 NWAM_NCU_PROP_IPV6_ADDRSRC, nwam_strerror(err));
923 985 } else {
924 986 for (i = 0; i < numvalues; i++) {
925 987 switch (addrsrcvalue[i]) {
926 988 case NWAM_ADDRSRC_DHCP:
927 989 nif->nwamd_if_stateful_requested = B_TRUE;
928 990 break;
929 991 case NWAM_ADDRSRC_AUTOCONF:
930 992 nif->nwamd_if_stateless_requested = B_TRUE;
931 993 break;
932 994 case NWAM_ADDRSRC_STATIC:
933 995 static_addr = B_TRUE;
934 996 break;
935 997 default:
936 998 break;
937 999 }
938 1000 }
939 1001 nwam_value_free(ncu_prop);
940 1002 }
941 1003 /*
942 1004 * Both stateful and stateless share the same nwamd_if_address because
943 1005 * only one ipaddr for both of these addresses can be created.
944 1006 * ipadm_create_addr() adds both addresses from the same ipaddr.
945 1007 */
946 1008 if (nif->nwamd_if_stateful_requested ||
947 1009 nif->nwamd_if_stateless_requested) {
948 1010 ipstatus = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
949 1011 ncu_data->ncu_name, &ipaddr);
950 1012 if (ipstatus != IPADM_SUCCESS) {
951 1013 nlog(LOG_ERR, "populate_ip_ncu_properties: "
952 1014 "ipadm_create_addrobj failed for v6 "
953 1015 "stateless/stateful: %s",
954 1016 ipadm_status2str(ipstatus));
955 1017 goto skip_ipv6_addrconf;
956 1018 }
957 1019 /* create_addrobj sets both stateless and stateful to B_TRUE */
958 1020 if (!nif->nwamd_if_stateful_requested) {
959 1021 ipstatus = ipadm_set_stateful(ipaddr, B_FALSE);
960 1022 if (ipstatus != IPADM_SUCCESS) {
961 1023 nlog(LOG_ERR, "populate_ip_ncu_properties: "
962 1024 "ipadm_set_stateful failed for v6: %s",
963 1025 ipadm_status2str(ipstatus));
964 1026 ipadm_destroy_addrobj(ipaddr);
965 1027 goto skip_ipv6_addrconf;
966 1028 }
967 1029 }
968 1030 if (!nif->nwamd_if_stateless_requested) {
969 1031 ipstatus = ipadm_set_stateless(ipaddr, B_FALSE);
970 1032 if (ipstatus != IPADM_SUCCESS) {
971 1033 nlog(LOG_ERR, "populate_ip_ncu_properties: "
972 1034 "ipadm_set_stateless failed for v6: %s",
973 1035 ipadm_status2str(ipstatus));
974 1036 ipadm_destroy_addrobj(ipaddr);
975 1037 goto skip_ipv6_addrconf;
976 1038 }
977 1039 }
978 1040 if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) {
979 1041 (*nifa)->family = AF_INET6;
980 1042 (*nifa)->ipaddr_atype = IPADM_ADDR_IPV6_ADDRCONF;
981 1043 (*nifa)->ipaddr = ipaddr;
982 1044 nifa = &((*nifa)->next);
983 1045 *nifa = NULL;
984 1046 } else {
985 1047 nlog(LOG_ERR, "populate_ip_ncu_properties: "
986 1048 "couldn't allocate nwamd address for "
987 1049 "v6 stateless/stateful: %s", strerror(errno));
|
↓ open down ↓ |
126 lines elided |
↑ open up ↑ |
988 1050 ipadm_destroy_addrobj(ipaddr);
989 1051 }
990 1052 }
991 1053
992 1054 skip_ipv6_addrconf:
993 1055 /* ipv6-addr */
994 1056 if (static_addr) {
995 1057 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
996 1058 &numvalues, NWAM_NCU_PROP_IPV6_ADDR)) != NWAM_SUCCESS) {
997 1059 nlog(LOG_ERR, "populate_ip_ncu_properties: "
998 - "could not get %s value; %s",
1060 + "could not get %s value: %s",
999 1061 NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err));
1000 1062 } else {
1001 1063 for (i = 0; i < numvalues; i++) {
1002 1064 ipstatus = ipadm_create_addrobj(
1003 1065 IPADM_ADDR_STATIC, ncu_data->ncu_name,
1004 1066 &ipaddr);
1005 1067 if (ipstatus != IPADM_SUCCESS) {
1006 1068 nlog(LOG_ERR,
1007 1069 "populate_ip_ncu_properties: "
1008 1070 "ipadm_create_addrobj failed "
1009 1071 "for %s: %s", addrvalue[i],
1010 1072 ipadm_status2str(ipstatus));
1011 1073 continue;
1012 1074 }
1013 1075 /* ipadm_set_addr takes <addr>[/<mask>] */
1014 1076 ipstatus = ipadm_set_addr(ipaddr, addrvalue[i],
1015 1077 AF_INET6);
1016 1078 if (ipstatus != IPADM_SUCCESS) {
1017 1079 nlog(LOG_ERR,
1018 1080 "populate_ip_ncu_properties: "
1019 1081 "ipadm_set_addr failed for %s: %s",
1020 1082 addrvalue[i],
1021 1083 ipadm_status2str(ipstatus));
1022 1084 ipadm_destroy_addrobj(ipaddr);
1023 1085 continue;
1024 1086 }
1025 1087
1026 1088 if ((*nifa = calloc(sizeof (**nifa), 1))
1027 1089 != NULL) {
1028 1090 (*nifa)->family = AF_INET6;
1029 1091 (*nifa)->ipaddr_atype =
1030 1092 IPADM_ADDR_STATIC;
1031 1093 (*nifa)->ipaddr = ipaddr;
1032 1094 nifa = &((*nifa)->next);
1033 1095 } else {
1034 1096 nlog(LOG_ERR,
1035 1097 "populate_ip_ncu_properties: "
1036 1098 "couldn't allocate nwamd address "
1037 1099 "for %s: %s", addrvalue[i],
1038 1100 strerror(errno));
1039 1101 ipadm_destroy_addrobj(ipaddr);
1040 1102 }
1041 1103 }
1042 1104 *nifa = NULL;
1043 1105
1044 1106 nwam_value_free(ncu_prop);
1045 1107 }
1046 1108 }
1047 1109
1048 1110 /* get default route, if any */
1049 1111 if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue,
1050 1112 &numvalues, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE)) == NWAM_SUCCESS) {
1051 1113 /* Only one default route is allowed. */
1052 1114 nif->nwamd_if_ipv6_default_route.sin6_family = AF_INET6;
1053 1115 (void) inet_pton(AF_INET6, addrvalue[0],
1054 1116 &(nif->nwamd_if_ipv6_default_route.sin6_addr));
1055 1117 nif->nwamd_if_ipv6_default_route_set = B_TRUE;
1056 1118 nwam_value_free(ncu_prop);
1057 1119 }
1058 1120
1059 1121 skip_ipv6:
1060 1122 ;
1061 1123 }
1062 1124
1063 1125 static nwamd_ncu_t *
1064 1126 nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name)
1065 1127 {
1066 1128 nwamd_ncu_t *rv;
1067 1129
1068 1130 nlog(LOG_DEBUG, "nwamd_ncu_init(%d, %s)", ncu_type, name);
1069 1131
1070 1132 if ((rv = calloc(1, sizeof (*rv))) == NULL)
1071 1133 return (NULL);
1072 1134
1073 1135 rv->ncu_type = ncu_type;
1074 1136 rv->ncu_name = strdup(name);
1075 1137 rv->ncu_enabled = B_FALSE;
1076 1138
1077 1139 /* Initialize link/interface-specific data */
1078 1140 if (rv->ncu_type == NWAM_NCU_TYPE_LINK) {
1079 1141 (void) bzero(&rv->ncu_link, sizeof (nwamd_link_t));
1080 1142 (void) dladm_name2info(dld_handle, name,
1081 1143 &rv->ncu_link.nwamd_link_id, NULL, NULL,
1082 1144 &rv->ncu_link.nwamd_link_media);
1083 1145 (void) pthread_mutex_init(
1084 1146 &rv->ncu_link.nwamd_link_wifi_mutex, NULL);
1085 1147 rv->ncu_link.nwamd_link_wifi_priority = MAXINT;
1086 1148 } else {
1087 1149 (void) bzero(&rv->ncu_if, sizeof (nwamd_if_t));
1088 1150 }
1089 1151
1090 1152 return (rv);
1091 1153 }
1092 1154
1093 1155 void
1094 1156 nwamd_ncu_free(nwamd_ncu_t *ncu)
1095 1157 {
1096 1158 if (ncu != NULL) {
1097 1159 assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK ||
1098 1160 ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE);
1099 1161 if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) {
1100 1162 struct nwamd_link *l = &ncu->ncu_link;
1101 1163 int i;
1102 1164
1103 1165 free(l->nwamd_link_wifi_key);
1104 1166 free(l->nwamd_link_mac_addr);
1105 1167 for (i = 0; i < l->nwamd_link_num_autopush; i++)
1106 1168 free(l->nwamd_link_autopush[i]);
1107 1169 } else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) {
1108 1170 struct nwamd_if_address *nifa;
1109 1171
1110 1172 nifa = ncu->ncu_if.nwamd_if_list;
1111 1173 while (nifa != NULL) {
1112 1174 struct nwamd_if_address *n;
1113 1175
1114 1176 n = nifa;
1115 1177 nifa = nifa->next;
1116 1178 ipadm_destroy_addrobj(n->ipaddr);
1117 1179 free(n);
1118 1180 }
1119 1181 }
1120 1182 free(ncu->ncu_name);
1121 1183 free(ncu);
1122 1184 }
1123 1185 }
1124 1186
1125 1187 static int
1126 1188 nwamd_ncu_display(nwamd_object_t ncu_obj, void *data)
1127 1189 {
1128 1190 nwamd_ncu_t *ncu = (nwamd_ncu_t *)ncu_obj->nwamd_object_data;
1129 1191 data = data;
1130 1192 nlog(LOG_DEBUG, "NCU (%p) %s state %s, %s",
1131 1193 (void *)ncu, ncu_obj->nwamd_object_name,
1132 1194 nwam_state_to_string(ncu_obj->nwamd_object_state),
1133 1195 nwam_aux_state_to_string(ncu_obj->nwamd_object_aux_state));
1134 1196 return (0);
1135 1197 }
1136 1198
1137 1199 void
1138 1200 nwamd_log_ncus(void)
1139 1201 {
1140 1202 nlog(LOG_DEBUG, "NCP %s", active_ncp);
1141 1203 (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, nwamd_ncu_display,
1142 1204 NULL);
1143 1205 }
1144 1206
1145 1207 int
1146 1208 nwamd_ncu_action(const char *ncu, const char *parent, nwam_action_t action)
1147 1209 {
1148 1210 nwamd_event_t ncu_event = nwamd_event_init_object_action
1149 1211 (NWAM_OBJECT_TYPE_NCU, ncu, parent, action);
1150 1212 if (ncu_event == NULL)
1151 1213 return (1);
1152 1214 nwamd_event_enqueue(ncu_event);
1153 1215 return (0);
1154 1216 }
1155 1217
1156 1218 static void
1157 1219 add_phys_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
1158 1220 {
1159 1221 dladm_status_t dlrtn;
1160 1222 uint32_t media;
1161 1223 boolean_t is_wireless;
1162 1224 nwam_error_t err;
1163 1225 nwam_ncu_handle_t ncuh;
1164 1226 uint64_t uintval;
1165 1227
1166 1228 if ((dlrtn = dladm_name2info(dld_handle, name, NULL, NULL, NULL,
1167 1229 &media)) != DLADM_STATUS_OK) {
1168 1230 char errmsg[DLADM_STRSIZE];
1169 1231 nlog(LOG_ERR, "failed to get media type for %s: %s", name,
1170 1232 dladm_status2str(dlrtn, errmsg));
1171 1233 return;
1172 1234 }
1173 1235 is_wireless = (media == DL_WIFI);
1174 1236
1175 1237 if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_LINK,
1176 1238 NWAM_NCU_CLASS_PHYS, &ncuh)) != NWAM_SUCCESS) {
1177 1239 nlog(LOG_ERR, "failed to create link ncu for %s: %s", name,
1178 1240 nwam_strerror(err));
1179 1241 if (err == NWAM_ENTITY_READ_ONLY) {
1180 1242 nwamd_event_t retry_event;
1181 1243
1182 1244 /*
1183 1245 * Root filesystem may be read-only, retry in
1184 1246 * a few seconds.
1185 1247 */
1186 1248 nlog(LOG_DEBUG, "Retrying addition of phys ncu for %s",
1187 1249 name);
1188 1250 retry_event = nwamd_event_init_link_action(name,
1189 1251 NWAM_ACTION_ADD);
1190 1252 if (retry_event != NULL) {
1191 1253 nwamd_event_enqueue_timed(retry_event,
1192 1254 NWAMD_READONLY_RETRY_INTERVAL);
1193 1255 }
1194 1256 }
1195 1257 return;
1196 1258 }
1197 1259
1198 1260 uintval = NWAM_ACTIVATION_MODE_PRIORITIZED;
1199 1261 if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
1200 1262 NWAM_NCU_PROP_ACTIVATION_MODE)) != NWAM_SUCCESS) {
1201 1263 goto finish;
1202 1264 }
1203 1265
1204 1266 uintval = is_wireless ? 1 : 0;
1205 1267 if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
1206 1268 NWAM_NCU_PROP_PRIORITY_GROUP)) != NWAM_SUCCESS) {
1207 1269 goto finish;
1208 1270 }
1209 1271
1210 1272 uintval = is_wireless ? NWAM_PRIORITY_MODE_EXCLUSIVE :
1211 1273 NWAM_PRIORITY_MODE_SHARED;
1212 1274 if ((err = nwamd_set_ncu_uint(ncuh, &uintval, 1,
1213 1275 NWAM_NCU_PROP_PRIORITY_MODE)) != NWAM_SUCCESS) {
1214 1276 goto finish;
1215 1277 }
1216 1278
1217 1279 err = nwam_ncu_commit(ncuh, 0);
1218 1280
1219 1281 finish:
1220 1282 nwam_ncu_free(ncuh);
1221 1283 if (err != NWAM_SUCCESS) {
1222 1284 nlog(LOG_ERR,
1223 1285 "failed to create automatic link ncu for %s: %s",
1224 1286 name, nwam_strerror(err));
1225 1287 }
1226 1288 }
1227 1289
1228 1290 static void
1229 1291 add_ip_ncu_to_ncp(nwam_ncp_handle_t ncph, const char *name)
1230 1292 {
1231 1293 nwam_error_t err;
1232 1294 nwam_ncu_handle_t ncuh;
1233 1295
1234 1296 if ((err = nwam_ncu_create(ncph, name, NWAM_NCU_TYPE_INTERFACE,
1235 1297 NWAM_NCU_CLASS_IP, &ncuh)) != NWAM_SUCCESS) {
1236 1298 nlog(LOG_ERR, "failed to create ip ncu for %s: %s", name,
1237 1299 nwam_strerror(err));
1238 1300 /*
1239 1301 * Root filesystem may be read-only, but no need to
1240 1302 * retry here since add_phys_ncu_to_ncp() enqueues
1241 1303 * a retry event which will lead to add_ip_ncu_to_ncp()
1242 1304 * being called.
1243 1305 */
1244 1306 return;
1245 1307 }
1246 1308
1247 1309 /* IP NCU has the default values, so nothing else to do */
1248 1310 err = nwam_ncu_commit(ncuh, 0);
1249 1311
1250 1312 finish:
1251 1313 nwam_ncu_free(ncuh);
1252 1314 if (err != NWAM_SUCCESS) {
1253 1315 nlog(LOG_ERR,
1254 1316 "failed to create ip ncu for %s: %s", name,
1255 1317 nwam_strerror(err));
1256 1318 }
1257 1319 }
1258 1320
1259 1321 static void
1260 1322 remove_ncu_from_ncp(nwam_ncp_handle_t ncph, const char *name,
1261 1323 nwam_ncu_type_t type)
1262 1324 {
1263 1325 nwam_error_t err;
1264 1326 nwam_ncu_handle_t ncuh;
1265 1327
1266 1328 if ((err = nwam_ncu_read(ncph, name, type, 0, &ncuh)) != NWAM_SUCCESS) {
1267 1329 nlog(LOG_ERR, "failed to read automatic ncu %s: %s", name,
1268 1330 nwam_strerror(err));
1269 1331 return;
1270 1332 }
1271 1333
1272 1334 err = nwam_ncu_destroy(ncuh, 0);
1273 1335 if (err != NWAM_SUCCESS) {
1274 1336 nlog(LOG_ERR, "failed to delete automatic ncu %s: %s", name,
1275 1337 nwam_strerror(err));
1276 1338 }
1277 1339 }
1278 1340
1279 1341 /*
1280 1342 * Device represented by NCU has been added or removed for the active
1281 1343 * User NCP. If an associated NCU of the given type is found, transition it
1282 1344 * to the appropriate state.
1283 1345 */
1284 1346 void
1285 1347 ncu_action_change_state(nwam_action_t action, nwam_ncu_type_t type,
1286 1348 const char *name)
1287 1349 {
1288 1350 nwamd_object_t ncu_obj = NULL;
1289 1351 nwamd_ncu_t *ncu;
1290 1352
1291 1353 if ((ncu_obj = nwamd_ncu_object_find(type, name)) == NULL)
1292 1354 return;
1293 1355
1294 1356 ncu = ncu_obj->nwamd_object_data;
1295 1357
1296 1358 /*
1297 1359 * If device has been added, transition from uninitialized to offline.
1298 1360 * If device has been removed, transition to uninitialized (via online*
1299 1361 * if the NCU is currently enabled in order to tear down config).
1300 1362 */
1301 1363 if (action == NWAM_ACTION_ADD) {
1302 1364 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1303 1365 ncu_obj->nwamd_object_name,
1304 1366 NWAM_STATE_OFFLINE, NWAM_AUX_STATE_CONDITIONS_NOT_MET);
1305 1367 } else {
1306 1368 if (ncu->ncu_enabled) {
1307 1369 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1308 1370 ncu_obj->nwamd_object_name,
1309 1371 NWAM_STATE_ONLINE_TO_OFFLINE,
1310 1372 NWAM_AUX_STATE_NOT_FOUND);
1311 1373 } else {
1312 1374 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1313 1375 ncu_obj->nwamd_object_name,
1314 1376 NWAM_STATE_UNINITIALIZED,
1315 1377 NWAM_AUX_STATE_NOT_FOUND);
1316 1378 }
1317 1379 }
1318 1380 nwamd_object_release(ncu_obj);
1319 1381 }
1320 1382
1321 1383 /*
1322 1384 * Called with hotplug sysevent or when nwam is started and walking the
1323 1385 * physical interfaces. Add/remove both link and interface NCUs from the
1324 1386 * Automatic NCP. Assumes that both link and interface NCUs don't exist.
1325 1387 */
1326 1388 void
1327 1389 nwamd_ncu_handle_link_action_event(nwamd_event_t event)
1328 1390 {
1329 1391 nwam_ncp_handle_t ncph;
1330 1392 nwam_ncu_type_t type;
1331 1393 nwam_action_t action =
1332 1394 event->event_msg->nwe_data.nwe_link_action.nwe_action;
1333 1395 nwam_error_t err;
1334 1396 char *name;
1335 1397 boolean_t automatic_ncp_active = B_FALSE;
1336 1398
1337 1399 if (action != NWAM_ACTION_ADD && action != NWAM_ACTION_REMOVE) {
1338 1400 nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
1339 1401 "invalid link action %s", nwam_action_to_string(action));
1340 1402 nwamd_event_do_not_send(event);
1341 1403 return;
1342 1404 }
1343 1405
1344 1406 nlog(LOG_DEBUG, "nwamd_ncu_handle_link_action_event: "
1345 1407 "link action '%s' event on %s", nwam_action_to_string(action),
1346 1408 event->event_object[0] == 0 ? "n/a" : event->event_object);
1347 1409
1348 1410 if ((err = nwam_ncu_typed_name_to_name(event->event_object, &type,
1349 1411 &name)) != NWAM_SUCCESS) {
1350 1412 nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
1351 1413 "translation from typedname error: %s", nwam_strerror(err));
1352 1414 nwamd_event_do_not_send(event);
1353 1415 return;
1354 1416 }
1355 1417
1356 1418 (void) pthread_mutex_lock(&active_ncp_mutex);
1357 1419 if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
1358 1420 active_ncph != NULL) {
1359 1421 automatic_ncp_active = B_TRUE;
1360 1422 }
1361 1423 (void) pthread_mutex_unlock(&active_ncp_mutex);
1362 1424
1363 1425 /*
1364 1426 * We could use active_ncph for cases where the Automatic NCP is active,
1365 1427 * but that would involve holding the active_ncp_mutex for too long.
1366 1428 */
1367 1429 if ((err = nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph))
1368 1430 == NWAM_ENTITY_NOT_FOUND) {
1369 1431 /* Automatic NCP doesn't exist, create it */
1370 1432 err = nwam_ncp_create(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph);
1371 1433 }
1372 1434 if (err != NWAM_SUCCESS)
1373 1435 goto fail;
1374 1436
1375 1437 /* add or remove NCUs from Automatic NCP */
1376 1438 if (action == NWAM_ACTION_ADD) {
1377 1439 add_phys_ncu_to_ncp(ncph, name);
1378 1440 add_ip_ncu_to_ncp(ncph, name);
1379 1441 } else {
1380 1442 /*
1381 1443 * Order is important here, remove IP NCU first to prevent
1382 1444 * propogation of down event from link to IP. No need to
1383 1445 * create REFRESH or DESTROY events. They are generated by
1384 1446 * nwam_ncu_commit() and nwam_ncu_destroy().
1385 1447 */
1386 1448 remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_INTERFACE);
1387 1449 remove_ncu_from_ncp(ncph, name, NWAM_NCU_TYPE_LINK);
1388 1450 }
1389 1451 nwam_ncp_free(ncph);
1390 1452
1391 1453 /*
1392 1454 * If the Automatic NCP is not active, and the associated NCUs
1393 1455 * exist, they must be moved into the appropriate states given the
1394 1456 * action that has occurred.
1395 1457 */
1396 1458 if (!automatic_ncp_active) {
1397 1459 ncu_action_change_state(action, NWAM_NCU_TYPE_INTERFACE, name);
1398 1460 ncu_action_change_state(action, NWAM_NCU_TYPE_LINK, name);
1399 1461 }
1400 1462
1401 1463 /* Need NCU check to evaluate state in light of added/removed NCUs */
1402 1464 if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
1403 1465 NWAM_OBJECT_TYPE_NCP, NULL)) {
1404 1466 nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
1405 1467 }
1406 1468
1407 1469 fail:
1408 1470 free(name);
1409 1471 if (err != NWAM_SUCCESS) {
1410 1472 nwamd_event_t retry_event = nwamd_event_init_link_action(name,
1411 1473 action);
1412 1474 if (retry_event == NULL) {
1413 1475 nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
1414 1476 "could not create retry event to read/create "
1415 1477 "%s NCP", NWAM_NCP_NAME_AUTOMATIC);
1416 1478 return;
1417 1479 }
1418 1480
1419 1481 nlog(LOG_ERR, "nwamd_ncu_handle_link_action_event: "
1420 1482 "could not read/create %s NCP, retrying in %d seconds",
1421 1483 NWAM_NCP_NAME_AUTOMATIC, NWAMD_READONLY_RETRY_INTERVAL);
1422 1484 nwamd_event_enqueue_timed(retry_event,
1423 1485 NWAMD_READONLY_RETRY_INTERVAL);
1424 1486 }
1425 1487 }
1426 1488
1427 1489 /*
1428 1490 * Figure out if this link is part of an aggregation. This is fairly
1429 1491 * inefficient since we generate this list for every query and search
1430 1492 * linearly. A better way would be to generate the list of links in an
1431 1493 * aggregation once and then check each link against it.
1432 1494 */
1433 1495 struct link_aggr_search_data {
1434 1496 datalink_id_t linkid;
1435 1497 boolean_t under;
1436 1498 };
1437 1499
1438 1500 static int
1439 1501 ncu_aggr_search(const char *name, void *data)
1440 1502 {
1441 1503 struct link_aggr_search_data *lasd = data;
1442 1504 dladm_aggr_grp_attr_t ginfo;
1443 1505 datalink_id_t linkid;
1444 1506 int i;
1445 1507
1446 1508 if (dladm_name2info(dld_handle, name, &linkid, NULL, NULL, NULL) !=
1447 1509 DLADM_STATUS_OK)
1448 1510 return (DLADM_WALK_CONTINUE);
1449 1511 if (dladm_aggr_info(dld_handle, linkid, &ginfo, DLADM_OPT_ACTIVE)
1450 1512 != DLADM_STATUS_OK || ginfo.lg_nports == 0)
1451 1513 return (DLADM_WALK_CONTINUE);
1452 1514
1453 1515 for (i = 0; i < ginfo.lg_nports; i++) {
1454 1516 if (lasd->linkid == ginfo.lg_ports[i].lp_linkid) {
1455 1517 lasd->under = B_TRUE;
1456 1518 return (DLADM_WALK_TERMINATE);
1457 1519 }
1458 1520 }
1459 1521 free(ginfo.lg_ports);
1460 1522 return (DLADM_WALK_CONTINUE);
1461 1523 }
1462 1524
1463 1525 static boolean_t
1464 1526 nwamd_link_belongs_to_an_aggr(const char *name)
1465 1527 {
1466 1528 struct link_aggr_search_data lasd;
1467 1529
1468 1530 if (dladm_name2info(dld_handle, name, &lasd.linkid, NULL, NULL, NULL)
1469 1531 != DLADM_STATUS_OK)
1470 1532 return (B_FALSE);
1471 1533 lasd.under = B_FALSE;
1472 1534 (void) dladm_walk(ncu_aggr_search, dld_handle, &lasd,
1473 1535 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1474 1536 return (lasd.under);
1475 1537 }
1476 1538
1477 1539 /*
1478 1540 * If NCU doesn't exist for interface with given name, enqueue a ADD
1479 1541 * LINK_ACTION event.
1480 1542 */
1481 1543 static int
1482 1544 ncu_create_link_action_event(const char *name, void *data)
1483 1545 {
1484 1546 nwam_ncp_handle_t ncph = data;
1485 1547 nwam_ncu_handle_t ncuh;
1486 1548 nwamd_event_t link_event;
1487 1549
1488 1550 /* Do not generate an event if this is a VirtualBox interface. */
1489 1551 if (strncmp(name, VBOX_IFACE_PREFIX, strlen(VBOX_IFACE_PREFIX)) == 0)
1490 1552 return (DLADM_WALK_CONTINUE);
1491 1553
1492 1554 /* Do not generate an event if this link belongs to another zone. */
1493 1555 if (!nwamd_link_belongs_to_this_zone(name))
1494 1556 return (DLADM_WALK_CONTINUE);
1495 1557
1496 1558 /* Do not generate an event if this link belongs to an aggregation. */
1497 1559 if (nwamd_link_belongs_to_an_aggr(name)) {
1498 1560 return (DLADM_WALK_CONTINUE);
1499 1561 }
1500 1562
1501 1563 /* Don't create an event if the NCU already exists. */
1502 1564 if (ncph != NULL && nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK, 0,
1503 1565 &ncuh) == NWAM_SUCCESS) {
1504 1566 nwam_ncu_free(ncuh);
1505 1567 return (DLADM_WALK_CONTINUE);
1506 1568 }
1507 1569
1508 1570 nlog(LOG_DEBUG, "ncu_create_link_action_event: adding ncus for %s",
1509 1571 name);
1510 1572
1511 1573 link_event = nwamd_event_init_link_action(name, NWAM_ACTION_ADD);
1512 1574 if (link_event != NULL)
1513 1575 nwamd_event_enqueue(link_event);
1514 1576
1515 1577 return (DLADM_WALK_CONTINUE);
1516 1578 }
1517 1579
1518 1580 /*
1519 1581 * Check if interface exists for this NCU. If not, enqueue a REMOVE
1520 1582 * LINK_ACTION event.
1521 1583 */
1522 1584 /* ARGSUSED */
1523 1585 static int
1524 1586 nwamd_destroy_ncu(nwam_ncu_handle_t ncuh, void *data)
1525 1587 {
1526 1588 char *name;
1527 1589 uint32_t flags;
1528 1590 nwamd_event_t link_event;
1529 1591
1530 1592 if (nwam_ncu_get_name(ncuh, &name) != NWAM_SUCCESS) {
1531 1593 nlog(LOG_ERR, "nwamd_destroy_ncu: could not get NCU name");
1532 1594 return (0);
1533 1595 }
1534 1596
1535 1597 /* Interfaces that exist return DLADM_OPT_ACTIVE flag */
1536 1598 if ((dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
1537 1599 == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) &&
1538 1600 !nwamd_link_belongs_to_an_aggr(name)) {
1539 1601 free(name);
1540 1602 return (0);
1541 1603 }
1542 1604
1543 1605 nlog(LOG_DEBUG, "nwamd_destroy_ncu: destroying ncus for %s", name);
1544 1606
1545 1607 link_event = nwamd_event_init_link_action(name, NWAM_ACTION_REMOVE);
1546 1608 if (link_event != NULL)
1547 1609 nwamd_event_enqueue(link_event);
1548 1610 free(name);
1549 1611 return (0);
1550 1612 }
1551 1613
1552 1614 /*
1553 1615 * Called when nwamd is starting up.
1554 1616 *
1555 1617 * Walk all NCUs and destroy any NCU from the Automatic NCP without an
1556 1618 * underlying interface (assumption here is that the interface was removed
1557 1619 * when nwam was disabled).
1558 1620 *
1559 1621 * Walk the physical interfaces and create ADD LINK_ACTION event, which
1560 1622 * will create appropriate interface and link NCUs in the Automatic NCP.
1561 1623 */
1562 1624 void
1563 1625 nwamd_walk_physical_configuration(void)
1564 1626 {
1565 1627 nwam_ncp_handle_t ncph;
1566 1628 datalink_class_t dlclass = DATALINK_CLASS_PHYS;
1567 1629 zoneid_t zoneid = getzoneid();
1568 1630
1569 1631 (void) pthread_mutex_lock(&active_ncp_mutex);
1570 1632 if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) == 0 &&
1571 1633 active_ncph != NULL) {
1572 1634 ncph = active_ncph;
1573 1635 } else {
1574 1636 if (nwam_ncp_read(NWAM_NCP_NAME_AUTOMATIC, 0, &ncph)
1575 1637 != NWAM_SUCCESS) {
1576 1638 ncph = NULL;
1577 1639 }
1578 1640 }
1579 1641
1580 1642 /* destroy NCUs for interfaces that don't exist */
1581 1643 if (ncph != NULL) {
1582 1644 (void) nwam_ncp_walk_ncus(ncph, nwamd_destroy_ncu, NULL,
1583 1645 NWAM_FLAG_NCU_TYPE_LINK, NULL);
1584 1646 }
1585 1647
1586 1648 /* In non-global zones NWAM can support VNICs */
1587 1649 if (zoneid != GLOBAL_ZONEID)
1588 1650 dlclass |= DATALINK_CLASS_VNIC;
1589 1651
1590 1652 /* create NCUs for interfaces without NCUs */
1591 1653 (void) dladm_walk(ncu_create_link_action_event, dld_handle, ncph,
1592 1654 dlclass, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1593 1655
1594 1656 if (strcmp(active_ncp, NWAM_NCP_NAME_AUTOMATIC) != 0 ||
1595 1657 active_ncph == NULL) {
1596 1658 nwam_ncp_free(ncph);
1597 1659 }
1598 1660 (void) pthread_mutex_unlock(&active_ncp_mutex);
1599 1661 }
1600 1662
1601 1663 /*
1602 1664 * Handle NCU initialization/refresh event.
1603 1665 */
1604 1666 void
1605 1667 nwamd_ncu_handle_init_event(nwamd_event_t event)
1606 1668 {
1607 1669 nwamd_object_t object = NULL;
1608 1670 nwam_ncu_handle_t ncuh;
1609 1671 nwamd_ncu_t *ncu = NULL;
1610 1672 nwam_error_t err;
1611 1673 nwam_ncu_type_t type;
1612 1674 char *name;
1613 1675 uint32_t flags;
1614 1676 boolean_t new = B_TRUE;
1615 1677
1616 1678 nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event(%s)",
1617 1679 event->event_object);
1618 1680
1619 1681 /* Get base linkname rather than interface:linkname or link:linkname */
1620 1682 err = nwam_ncu_typed_name_to_name(event->event_object,
1621 1683 &type, &name);
1622 1684 if (err != NWAM_SUCCESS) {
1623 1685 nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
1624 1686 "nwam_ncu_typed_name_to_name returned %s",
1625 1687 nwam_strerror(err));
1626 1688 nwamd_event_do_not_send(event);
1627 1689 return;
1628 1690 }
1629 1691
1630 1692 (void) pthread_mutex_lock(&active_ncp_mutex);
1631 1693 if (active_ncph == NULL) {
1632 1694 nlog(LOG_DEBUG,
1633 1695 "nwamd_ncu_handle_init_event: active NCP handle NULL");
1634 1696 nwamd_event_do_not_send(event);
1635 1697 free(name);
1636 1698 (void) pthread_mutex_unlock(&active_ncp_mutex);
1637 1699 return;
1638 1700 }
1639 1701 err = nwam_ncu_read(active_ncph, event->event_object,
1640 1702 type, 0, &ncuh);
1641 1703 (void) pthread_mutex_unlock(&active_ncp_mutex);
1642 1704 if (err != NWAM_SUCCESS) {
1643 1705 nlog(LOG_ERR, "nwamd_ncu_handle_init_event: "
1644 1706 "could not read object '%s': %s",
1645 1707 event->event_object, nwam_strerror(err));
1646 1708 free(name);
1647 1709 nwamd_event_do_not_send(event);
1648 1710 return;
1649 1711 }
1650 1712
1651 1713 if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
1652 1714 event->event_object)) != NULL)
1653 1715 new = B_FALSE;
1654 1716
1655 1717 /*
1656 1718 * For new NCUs, or interface NCUs, we (re)initialize data from scratch.
1657 1719 * For link NCUs, we want to retain object data.
1658 1720 */
1659 1721 switch (type) {
1660 1722 case NWAM_NCU_TYPE_LINK:
1661 1723 if (new) {
1662 1724 ncu = nwamd_ncu_init(type, name);
1663 1725 } else {
1664 1726 ncu = object->nwamd_object_data;
1665 1727 nwam_ncu_free(object->nwamd_object_handle);
1666 1728 }
1667 1729 populate_common_ncu_properties(ncuh, ncu);
1668 1730 populate_link_ncu_properties(ncuh, ncu);
1669 1731 break;
1670 1732 case NWAM_NCU_TYPE_INTERFACE:
1671 1733 if (!new) {
1672 1734 nwam_ncu_free(object->nwamd_object_handle);
1673 1735 nwamd_ncu_free(object->nwamd_object_data);
1674 1736 }
1675 1737 ncu = nwamd_ncu_init(type, name);
1676 1738 populate_common_ncu_properties(ncuh, ncu);
1677 1739 populate_ip_ncu_properties(ncuh, ncu);
1678 1740 break;
1679 1741 default:
1680 1742 nlog(LOG_ERR, "unknown ncu type %d", type);
1681 1743 free(name);
1682 1744 nwam_ncu_free(ncuh);
1683 1745 nwamd_event_do_not_send(event);
1684 1746 nwamd_object_release(object);
1685 1747 return;
1686 1748 }
1687 1749
1688 1750 if (new) {
1689 1751 nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: didn't find "
1690 1752 "ncu so create it %s", name);
1691 1753 object = nwamd_object_init(NWAM_OBJECT_TYPE_NCU,
1692 1754 event->event_object, ncuh, ncu);
1693 1755 } else {
1694 1756 nlog(LOG_DEBUG, "nwamd_ncu_handle_init_event: refreshing "
1695 1757 "ncu %s", name);
1696 1758 object->nwamd_object_data = ncu;
1697 1759 object->nwamd_object_handle = ncuh;
1698 1760 }
1699 1761
1700 1762 /*
1701 1763 * If the physical link for this NCU doesn't exist in the system,
1702 1764 * the state should be UNINITIALIZED/NOT_FOUND. Interfaces that
1703 1765 * exist return DLADM_OPT_ACTIVE flag.
1704 1766 */
1705 1767 if (dladm_name2info(dld_handle, name, NULL, &flags, NULL, NULL)
1706 1768 != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) {
1707 1769 nlog(LOG_DEBUG, "nwam_ncu_handle_init_event: "
1708 1770 "interface for NCU %s doesn't exist",
1709 1771 event->event_object);
1710 1772 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1711 1773 object->nwamd_object_name, NWAM_STATE_UNINITIALIZED,
1712 1774 NWAM_AUX_STATE_NOT_FOUND);
1713 1775 free(name);
1714 1776 nwamd_object_release(object);
1715 1777 return;
1716 1778 }
1717 1779
1718 1780 /*
1719 1781 * If NCU is being initialized (rather than refreshed), the
1720 1782 * object_state is INITIALIZED (from nwamd_object_init()).
1721 1783 */
1722 1784 if (object->nwamd_object_state == NWAM_STATE_INITIALIZED) {
1723 1785 /*
1724 1786 * If the NCU is disabled, initial state should be DISABLED.
1725 1787 *
1726 1788 * Otherwise, the initial state will be
1727 1789 * OFFLINE/CONDITIONS_NOT_MET, and the link selection
1728 1790 * algorithm will do the rest.
1729 1791 */
1730 1792 if (!ncu->ncu_enabled) {
1731 1793 object->nwamd_object_state = NWAM_STATE_DISABLED;
1732 1794 object->nwamd_object_aux_state =
1733 1795 NWAM_AUX_STATE_MANUAL_DISABLE;
1734 1796 } else {
1735 1797 object->nwamd_object_state = NWAM_STATE_OFFLINE;
1736 1798 object->nwamd_object_aux_state =
1737 1799 NWAM_AUX_STATE_CONDITIONS_NOT_MET;
1738 1800 }
1739 1801 } else {
1740 1802 nwamd_link_t *link = &ncu->ncu_link;
1741 1803
1742 1804 /*
1743 1805 * Refresh NCU. Deal with disabled cases first, moving NCUs
1744 1806 * that are not disabled - but have the enabled value set - to
1745 1807 * the disabled state. Then handle cases where the NCU was
1746 1808 * disabled but is no longer. Finally, deal with refresh of
1747 1809 * link and interface NCUs, as these are handled differently.
1748 1810 */
1749 1811 if (!ncu->ncu_enabled) {
1750 1812 if (object->nwamd_object_state != NWAM_STATE_DISABLED) {
1751 1813 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1752 1814 object->nwamd_object_name,
1753 1815 NWAM_STATE_ONLINE_TO_OFFLINE,
1754 1816 NWAM_AUX_STATE_MANUAL_DISABLE);
1755 1817 }
1756 1818 goto done;
1757 1819 } else {
1758 1820 if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
1759 1821 int64_t c;
1760 1822
1761 1823 /*
1762 1824 * Try to activate the NCU if manual or
1763 1825 * prioritized (when priority <= current).
1764 1826 */
1765 1827 (void) pthread_mutex_lock(&active_ncp_mutex);
1766 1828 c = current_ncu_priority_group;
1767 1829 (void) pthread_mutex_unlock(&active_ncp_mutex);
1768 1830 if (link->nwamd_link_activation_mode ==
1769 1831 NWAM_ACTIVATION_MODE_MANUAL ||
1770 1832 (link->nwamd_link_activation_mode ==
1771 1833 NWAM_ACTIVATION_MODE_PRIORITIZED &&
1772 1834 link->nwamd_link_priority_mode <= c)) {
1773 1835 nwamd_object_set_state
1774 1836 (NWAM_OBJECT_TYPE_NCU,
1775 1837 object->nwamd_object_name,
1776 1838 NWAM_STATE_OFFLINE_TO_ONLINE,
1777 1839 NWAM_AUX_STATE_INITIALIZED);
1778 1840 } else {
1779 1841 nwamd_object_set_state
1780 1842 (NWAM_OBJECT_TYPE_NCU,
1781 1843 object->nwamd_object_name,
1782 1844 NWAM_STATE_OFFLINE_TO_ONLINE,
1783 1845 NWAM_AUX_STATE_INITIALIZED);
1784 1846 }
1785 1847 goto done;
1786 1848 }
1787 1849 }
1788 1850
1789 1851 switch (type) {
1790 1852 case NWAM_NCU_TYPE_LINK:
1791 1853 if (ncu->ncu_link.nwamd_link_media == DL_WIFI) {
1792 1854 /*
1793 1855 * Do rescan. If the current state and the
1794 1856 * active priority-group do not allow wireless
1795 1857 * network selection, then it won't happen.
1796 1858 */
1797 1859 (void) nwamd_wlan_scan(ncu->ncu_name);
1798 1860 }
1799 1861 break;
1800 1862 case NWAM_NCU_TYPE_INTERFACE:
1801 1863 /*
1802 1864 * If interface NCU is offline*, online or in
1803 1865 * maintenance, mark it down (from there, it will be
1804 1866 * reinitialized to reapply addresses).
1805 1867 */
1806 1868 if (object->nwamd_object_state != NWAM_STATE_OFFLINE) {
1807 1869 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1808 1870 object->nwamd_object_name,
1809 1871 NWAM_STATE_ONLINE_TO_OFFLINE,
1810 1872 NWAM_AUX_STATE_DOWN);
1811 1873 } else {
1812 1874 object->nwamd_object_state = NWAM_STATE_OFFLINE;
1813 1875 object->nwamd_object_aux_state =
1814 1876 NWAM_AUX_STATE_CONDITIONS_NOT_MET;
1815 1877 }
1816 1878 break;
1817 1879 }
1818 1880 }
1819 1881
1820 1882 done:
1821 1883 if (type == NWAM_NCU_TYPE_LINK &&
1822 1884 !nwamd_event_enqueued(NWAM_EVENT_TYPE_NCU_CHECK,
1823 1885 NWAM_OBJECT_TYPE_NCP, NULL)) {
1824 1886 nwamd_create_ncu_check_event(NEXT_FEW_SECONDS);
1825 1887 }
1826 1888 free(name);
1827 1889 nwamd_object_release(object);
1828 1890 }
1829 1891
1830 1892 void
1831 1893 nwamd_ncu_handle_fini_event(nwamd_event_t event)
1832 1894 {
1833 1895 nwamd_object_t object;
1834 1896 nwamd_event_t state_event;
1835 1897
1836 1898 nlog(LOG_DEBUG, "nwamd_ncu_handle_fini_event(%s)",
1837 1899 event->event_object);
1838 1900
1839 1901 /*
1840 1902 * Simulate a state event so that the state machine can correctly
1841 1903 * disable the NCU. Then free up allocated objects.
1842 1904 */
1843 1905 state_event = nwamd_event_init_object_state(NWAM_OBJECT_TYPE_NCU,
1844 1906 event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
1845 1907 NWAM_AUX_STATE_UNINITIALIZED);
1846 1908 if (state_event == NULL) {
1847 1909 nwamd_event_do_not_send(event);
1848 1910 return;
1849 1911 }
1850 1912 nwamd_ncu_handle_state_event(state_event);
1851 1913 nwamd_event_fini(state_event);
1852 1914
1853 1915 if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
1854 1916 event->event_object)) == NULL) {
1855 1917 nlog(LOG_INFO, "nwamd_ncu_handle_fini_event: "
1856 1918 "ncu %s not found", event->event_object);
1857 1919 nwamd_event_do_not_send(event);
1858 1920 return;
1859 1921 }
1860 1922 nwamd_object_release_and_destroy(object);
1861 1923 }
1862 1924
1863 1925 void
1864 1926 nwamd_ncu_handle_action_event(nwamd_event_t event)
1865 1927 {
1866 1928 nwamd_object_t object;
1867 1929
1868 1930 (void) pthread_mutex_lock(&active_ncp_mutex);
1869 1931 if (strcmp(event->event_msg->nwe_data.nwe_object_action.nwe_parent,
1870 1932 active_ncp) != 0) {
1871 1933 nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: action for "
1872 1934 "inactive NCP %s, nothing to do",
1873 1935 event->event_msg->nwe_data.nwe_object_action.nwe_parent);
1874 1936 (void) pthread_mutex_unlock(&active_ncp_mutex);
1875 1937 return;
1876 1938 }
1877 1939 (void) pthread_mutex_unlock(&active_ncp_mutex);
1878 1940
1879 1941 switch (event->event_msg->nwe_data.nwe_object_action.nwe_action) {
1880 1942 case NWAM_ACTION_ENABLE:
1881 1943 object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
1882 1944 event->event_object);
1883 1945 if (object == NULL) {
1884 1946 nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
1885 1947 "could not find ncu %s", event->event_object);
1886 1948 nwamd_event_do_not_send(event);
1887 1949 return;
1888 1950 }
1889 1951 if (object->nwamd_object_state == NWAM_STATE_ONLINE) {
1890 1952 nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
1891 1953 "ncu %s already online, nothing to do",
1892 1954 event->event_object);
1893 1955 nwamd_object_release(object);
1894 1956 return;
1895 1957 }
1896 1958 nwamd_object_release(object);
1897 1959
1898 1960 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1899 1961 event->event_object, NWAM_STATE_OFFLINE_TO_ONLINE,
1900 1962 NWAM_AUX_STATE_INITIALIZED);
1901 1963 break;
1902 1964 case NWAM_ACTION_DISABLE:
1903 1965 object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
1904 1966 event->event_object);
1905 1967 if (object == NULL) {
1906 1968 nlog(LOG_ERR, "nwamd_ncu_handle_action_event: "
1907 1969 "could not find ncu %s", event->event_object);
1908 1970 nwamd_event_do_not_send(event);
1909 1971 return;
1910 1972 }
1911 1973 if (object->nwamd_object_state == NWAM_STATE_DISABLED) {
1912 1974 nlog(LOG_DEBUG, "nwamd_ncu_handle_action_event: "
1913 1975 "ncu %s already disabled, nothing to do",
1914 1976 event->event_object);
1915 1977 nwamd_object_release(object);
1916 1978 return;
1917 1979 }
1918 1980 nwamd_object_release(object);
1919 1981
1920 1982 nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
1921 1983 event->event_object, NWAM_STATE_ONLINE_TO_OFFLINE,
1922 1984 NWAM_AUX_STATE_MANUAL_DISABLE);
1923 1985 break;
1924 1986 case NWAM_ACTION_ADD:
1925 1987 case NWAM_ACTION_REFRESH:
1926 1988 nwamd_ncu_handle_init_event(event);
1927 1989 break;
1928 1990 case NWAM_ACTION_DESTROY:
1929 1991 nwamd_ncu_handle_fini_event(event);
1930 1992 break;
1931 1993 default:
1932 1994 nlog(LOG_INFO, "nwam_ncu_handle_action_event: "
1933 1995 "unexpected action");
1934 1996 nwamd_event_do_not_send(event);
1935 1997 break;
1936 1998 }
1937 1999 }
1938 2000
1939 2001 void
1940 2002 nwamd_ncu_handle_state_event(nwamd_event_t event)
1941 2003 {
1942 2004 nwamd_object_t object;
1943 2005 nwam_state_t old_state, new_state;
1944 2006 nwam_aux_state_t new_aux_state;
1945 2007 nwamd_ncu_t *ncu;
1946 2008 boolean_t is_link, enabled, prioritized = B_FALSE;
1947 2009 char linkname[NWAM_MAX_NAME_LEN];
1948 2010 nwam_event_t m = event->event_msg;
1949 2011
1950 2012 if ((object = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
1951 2013 event->event_object)) == NULL) {
1952 2014 nlog(LOG_INFO, "nwamd_ncu_handle_state_event %lld: "
1953 2015 "state event for nonexistent NCU %s", event->event_id,
1954 2016 event->event_object);
1955 2017 nwamd_event_do_not_send(event);
1956 2018 return;
1957 2019 }
1958 2020 ncu = object->nwamd_object_data;
1959 2021 old_state = object->nwamd_object_state;
1960 2022 new_state = event->event_msg->nwe_data.nwe_object_state.nwe_state;
1961 2023 new_aux_state =
1962 2024 event->event_msg->nwe_data.nwe_object_state.nwe_aux_state;
1963 2025
1964 2026 /*
1965 2027 * For NCU state changes, we need to supply the parent NCP name also,
1966 2028 * regardless of whether the event is handled or not. It is best to
1967 2029 * fill this in here as we have the object lock - when we create
1968 2030 * object state events we sometimes do not have the object lock, but
1969 2031 * at this point in consuming the events (and prior to the associated
1970 2032 * event message being sent out) we do.
1971 2033 */
1972 2034 (void) strlcpy(m->nwe_data.nwe_object_state.nwe_parent, ncu->ncu_parent,
1973 2035 sizeof (m->nwe_data.nwe_object_state.nwe_parent));
1974 2036
1975 2037 /*
1976 2038 * If we receive a state change event moving this NCU to
1977 2039 * DHCP_TIMED_OUT or UP state but this NCU is already ONLINE, then
1978 2040 * ignore this state change event.
1979 2041 */
1980 2042 if ((new_aux_state == NWAM_AUX_STATE_IF_DHCP_TIMED_OUT ||
1981 2043 new_aux_state == NWAM_AUX_STATE_UP) &&
1982 2044 object->nwamd_object_state == NWAM_STATE_ONLINE) {
1983 2045 nlog(LOG_INFO, "nwamd_ncu_handle_state_event: "
1984 2046 "NCU %s already online, not going to '%s' state",
1985 2047 object->nwamd_object_name,
1986 2048 nwam_aux_state_to_string(new_aux_state));
1987 2049 nwamd_event_do_not_send(event);
1988 2050 nwamd_object_release(object);
1989 2051 return;
1990 2052 }
1991 2053
1992 2054 if (new_state == object->nwamd_object_state &&
1993 2055 new_aux_state == object->nwamd_object_aux_state) {
1994 2056 nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
1995 2057 "NCU %s already in state (%s, %s)",
1996 2058 object->nwamd_object_name, nwam_state_to_string(new_state),
1997 2059 nwam_aux_state_to_string(new_aux_state));
1998 2060 nwamd_object_release(object);
1999 2061 return;
2000 2062 }
2001 2063
2002 2064 if (old_state == NWAM_STATE_MAINTENANCE &&
2003 2065 (new_state == NWAM_STATE_ONLINE ||
2004 2066 (new_state == NWAM_STATE_OFFLINE_TO_ONLINE &&
2005 2067 new_aux_state != NWAM_AUX_STATE_INITIALIZED))) {
2006 2068 nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
2007 2069 "NCU %s cannot transition from state %s to state (%s, %s)",
2008 2070 object->nwamd_object_name, nwam_state_to_string(old_state),
2009 2071 nwam_state_to_string(new_state),
2010 2072 nwam_aux_state_to_string(new_aux_state));
2011 2073 nwamd_event_do_not_send(event);
2012 2074 nwamd_object_release(object);
2013 2075 return;
2014 2076 }
2015 2077
2016 2078 object->nwamd_object_state = new_state;
2017 2079 object->nwamd_object_aux_state = new_aux_state;
2018 2080
2019 2081 nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: changing state for NCU "
2020 2082 "%s to (%s, %s)", object->nwamd_object_name,
2021 2083 nwam_state_to_string(object->nwamd_object_state),
2022 2084 nwam_aux_state_to_string(object->nwamd_object_aux_state));
2023 2085
2024 2086 is_link = (ncu->ncu_type == NWAM_NCU_TYPE_LINK);
2025 2087 if (is_link)
2026 2088 (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname));
2027 2089 prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK &&
2028 2090 ncu->ncu_link.nwamd_link_activation_mode ==
2029 2091 NWAM_ACTIVATION_MODE_PRIORITIZED);
2030 2092 enabled = ncu->ncu_enabled;
2031 2093
2032 2094 nwamd_object_release(object);
2033 2095
2034 2096 /*
2035 2097 * State machine for NCUs
2036 2098 */
2037 2099 switch (new_state) {
2038 2100 case NWAM_STATE_OFFLINE_TO_ONLINE:
2039 2101 if (enabled) {
2040 2102 nwamd_ncu_state_machine(event->event_object);
2041 2103 } else {
2042 2104 nlog(LOG_DEBUG, "nwamd_ncu_handle_state_event: "
2043 2105 "cannot move disabled NCU %s online",
2044 2106 event->event_object);
2045 2107 nwamd_event_do_not_send(event);
2046 2108 }
2047 2109 break;
2048 2110
2049 2111 case NWAM_STATE_ONLINE_TO_OFFLINE:
2050 2112 nwamd_ncu_state_machine(event->event_object);
2051 2113 break;
2052 2114
2053 2115 case NWAM_STATE_ONLINE:
2054 2116 /*
2055 2117 * We usually don't need to do anything when we're in the
2056 2118 * ONLINE state. However, for WiFi we can be in INIT or
2057 2119 * SCAN aux states while being ONLINE.
2058 2120 */
2059 2121 nwamd_ncu_state_machine(event->event_object);
2060 2122 break;
2061 2123
2062 2124 case NWAM_STATE_OFFLINE:
2063 2125 /* Reassess priority group now member is offline */
2064 2126 if (prioritized) {
2065 2127 nwamd_create_ncu_check_event(0);
2066 2128 }
2067 2129 break;
2068 2130
2069 2131 case NWAM_STATE_DISABLED:
2070 2132 case NWAM_STATE_UNINITIALIZED:
2071 2133 case NWAM_STATE_MAINTENANCE:
2072 2134 case NWAM_STATE_DEGRADED:
2073 2135 default:
2074 2136 /* do nothing */
2075 2137 break;
2076 2138 }
2077 2139
2078 2140 if (is_link) {
2079 2141 if ((new_state == NWAM_STATE_ONLINE_TO_OFFLINE &&
2080 2142 new_aux_state != NWAM_AUX_STATE_UNINITIALIZED &&
2081 2143 new_aux_state != NWAM_AUX_STATE_NOT_FOUND) ||
2082 2144 new_state == NWAM_STATE_DISABLED) {
2083 2145 /*
2084 2146 * Going offline, propogate down event to IP NCU. Do
2085 2147 * not propogate event if new aux state is uninitialized
2086 2148 * or not found as these auxiliary states signify
2087 2149 * that an NCP switch/device removal is in progress.
2088 2150 */
2089 2151 nwamd_propogate_link_up_down_to_ip(linkname, B_FALSE);
2090 2152 }
2091 2153 if (new_state == NWAM_STATE_ONLINE) {
2092 2154 /* gone online, propogate up event to IP NCU */
2093 2155 nwamd_propogate_link_up_down_to_ip(linkname, B_TRUE);
2094 2156 }
2095 2157 } else {
2096 2158 /* If IP NCU is online, reasses priority group */
2097 2159 if (new_state == NWAM_STATE_ONLINE)
2098 2160 nwamd_create_ncu_check_event(0);
2099 2161 }
2100 2162 }
|
↓ open down ↓ |
1092 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX