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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This file is here for legacy support.
34 #include <libdllink.h>
42 #include "known_wlans.h"
48 * This file formerly contained the routines that manipulate Link Layer
49 * Profiles (aka LLPs) and various support functions. Now only code
50 * necessary for parsing the legacy /etc/nwam/llp file on upgrade is included,
51 * since this legacy configuration needs to be translated into the User NCP.
54 #define OUR_OLD_DHCP_WAIT_TIME_PROP_NAME "dhcp_wait_time"
55 #define OUR_OLD_USE_NET_SVC_PROP_NAME "use_net_svc"
56 #define OUR_OLD_IDLE_TIME_PROP_NAME "idle_time"
58 static struct qelem llp_list
;
61 * Global variable to hold the highest priority. Need to use the atomic
62 * integer arithmetic functions to update it.
64 static uint32_t llp_highest_pri
;
66 /* Specifies if static address has been configured in /etc/nwam/llp */
67 static boolean_t static_configured
= B_FALSE
;
69 static enum interface_type
70 find_if_type(const char *name
)
73 enum interface_type type
;
76 nlog(LOG_DEBUG
, "find_if_type: no ifname; "
77 "returning IF_UNKNOWN");
82 if (dladm_name2info(dld_handle
, name
, NULL
, NULL
, NULL
, &media
) !=
84 if (strncmp(name
, "ip.tun", 6) == 0 ||
85 strncmp(name
, "ip6.tun", 7) == 0 ||
86 strncmp(name
, "ip.6to4tun", 10) == 0)
88 * We'll need to update our tunnel detection once
89 * the clearview/tun project is integrated; tunnel
90 * names won't necessarily be ip.tunN.
93 } else if (media
== DL_WIFI
) {
105 while (llp_list
.q_forw
!= &llp_list
) {
106 llp
= (llp_t
*)llp_list
.q_forw
;
107 remque(&llp
->llp_links
);
108 free(llp
->llp_ipv6addrstr
);
109 free(llp
->llp_ipv4addrstr
);
117 llp_list
.q_forw
= llp_list
.q_back
= &llp_list
;
121 llp_lookup(const char *link
)
128 for (llp
= (llp_t
*)llp_list
.q_forw
; llp
!= (llp_t
*)&llp_list
;
129 llp
= (llp_t
*)llp
->llp_links
.q_forw
) {
130 if (strcmp(link
, llp
->llp_lname
) == 0)
133 if (llp
== (llp_t
*)&llp_list
)
139 * Create the named LLP with default settings. Called only in main thread.
142 llp_add(const char *name
)
146 if ((llp
= calloc(1, sizeof (llp_t
))) == NULL
) {
147 nlog(LOG_ERR
, "llp_add: cannot allocate LLP: %m");
151 if (strlcpy(llp
->llp_lname
, name
, sizeof (llp
->llp_lname
)) >=
152 sizeof (llp
->llp_lname
)) {
153 nlog(LOG_ERR
, "llp_add: linkname '%s' too long; ignoring entry",
159 llp
->llp_fileorder
= llp
->llp_pri
=
160 atomic_add_32_nv(&llp_highest_pri
, 1);
161 llp
->llp_ipv4src
= IPV4SRC_DHCP
;
162 llp
->llp_type
= find_if_type(llp
->llp_lname
);
163 llp
->llp_ipv6onlink
= B_TRUE
;
166 * should be a no-op, but for now, make sure we only
167 * create llps for wired and wireless interfaces.
169 if (llp
->llp_type
!= IF_WIRED
&& llp
->llp_type
!= IF_WIRELESS
) {
170 nlog(LOG_ERR
, "llp_add: wrong type of interface for %s", name
);
174 insque(&llp
->llp_links
, llp_list
.q_back
);
176 nlog(LOG_DEBUG
, "llp_add: "
177 "created llp for link %s, priority %d", llp
->llp_lname
,
183 parse_llp_config(void)
185 static const char STATICSTR
[] = "static";
186 static const char DHCP
[] = "dhcp";
187 static const char IPV6
[] = "ipv6";
188 static const char NOIPV6
[] = "noipv6";
189 static const char PRIORITY
[] = "priority";
192 char *cp
, *lasts
, *lstr
, *srcstr
, *addrstr
;
198 fp
= fopen(LLPFILE
, "r+");
202 nlog(LOG_ERR
, "parse_llp_config: "
203 "open legacy LLP config file: %m");
207 for (lnum
= 1; fgets(line
, sizeof (line
), fp
) != NULL
; lnum
++) {
208 if (line
[strlen(line
) - 1] == '\n')
209 line
[strlen(line
) - 1] = '\0';
215 if (*cp
== '#' || *cp
== '\0')
218 nlog(LOG_DEBUG
, "parse_llp_config: "
219 "parsing legacy LLP conf file line %d...", lnum
);
221 if (((lstr
= strtok_r(cp
, " \t", &lasts
)) == NULL
) ||
222 ((srcstr
= strtok_r(NULL
, " \t", &lasts
)) == NULL
)) {
223 nlog(LOG_ERR
, "parse_llp_config: line %d: "
224 "not enough tokens; ignoring entry", lnum
);
228 if ((llp
= llp_lookup(lstr
)) == NULL
&&
229 (llp
= llp_add(lstr
)) == NULL
) {
230 nlog(LOG_ERR
, "parse_llp_config: line %d: "
231 "cannot add entry", lnum
);
235 if (strcasecmp(srcstr
, STATICSTR
) == 0) {
236 if ((addrstr
= strtok_r(NULL
, " \t", &lasts
)) == NULL
||
237 atoi(addrstr
) == 0) { /* crude check for number */
238 nlog(LOG_ERR
, "parse_llp_config: line %d: "
239 "missing ipaddr for static config", lnum
);
240 } else if ((addrstr
= strdup(addrstr
)) == NULL
) {
241 nlog(LOG_ERR
, "parse_llp_config: line %d: "
242 "cannot save address", lnum
);
244 free(llp
->llp_ipv4addrstr
);
245 llp
->llp_ipv4src
= IPV4SRC_STATIC
;
246 llp
->llp_ipv4addrstr
= addrstr
;
249 } else if (strcasecmp(srcstr
, DHCP
) == 0) {
250 llp
->llp_ipv4src
= IPV4SRC_DHCP
;
252 } else if (strcasecmp(srcstr
, IPV6
) == 0) {
253 llp
->llp_ipv6onlink
= B_TRUE
;
254 if ((addrstr
= strtok_r(NULL
, " \t", &lasts
)) == NULL
) {
256 } else if ((addrstr
= strdup(addrstr
)) == NULL
) {
257 nlog(LOG_ERR
, "parse_llp_config: line %d: "
258 "cannot save address", lnum
);
260 free(llp
->llp_ipv6addrstr
);
261 llp
->llp_ipv6addrstr
= addrstr
;
264 } else if (strcasecmp(srcstr
, NOIPV6
) == 0) {
265 llp
->llp_ipv6onlink
= B_FALSE
;
267 } else if (strcasecmp(srcstr
, PRIORITY
) == 0) {
268 if ((addrstr
= strtok_r(NULL
, " \t", &lasts
)) == NULL
) {
270 "parse_llp_config: line %d: "
271 "missing priority value", lnum
);
273 llp
->llp_pri
= atoi(addrstr
);
277 nlog(LOG_ERR
, "parse_llp_config: line %d: "
278 "unrecognized field '%s'", lnum
, srcstr
);
287 * Translate legacy LLP config into the user NCP.
290 upgrade_llp_config(void)
293 nwam_ncp_handle_t user_ncp
;
294 nwam_ncu_handle_t phys_ncu
= NULL
, ip_ncu
= NULL
;
300 switch (parse_llp_config()) {
309 err
= nwam_ncp_create(NWAM_NCP_NAME_USER
, 0, &user_ncp
);
313 case NWAM_ERROR_BIND
:
314 case NWAM_ERROR_INTERNAL
:
315 nlog(LOG_ERR
, "upgrade_llp_config: "
316 "could not create User NCP: %s", nwam_strerror(err
));
320 nlog(LOG_ERR
, "upgrade_llp_config: error creating User NCP: %s",
326 nlog(LOG_DEBUG
, "upgrade_llp_config: walking llp list");
328 for (wp
= (llp_t
*)llp_list
.q_forw
; wp
!= (llp_t
*)&llp_list
;
329 wp
= (llp_t
*)wp
->llp_links
.q_forw
) {
331 nlog(LOG_DEBUG
, "upgrade_llp_config: "
332 "upgrading llp %s", wp
->llp_lname
);
334 if (nwam_ncu_create(user_ncp
, wp
->llp_lname
,
335 NWAM_NCU_TYPE_INTERFACE
, NWAM_NCU_CLASS_IP
, &ip_ncu
)
337 nwam_ncu_create(user_ncp
, wp
->llp_lname
, NWAM_NCU_TYPE_LINK
,
338 NWAM_NCU_CLASS_PHYS
, &phys_ncu
) != NWAM_SUCCESS
) {
339 nlog(LOG_ERR
, "upgrade_llp_config: llp %s: "
340 "could not create NCUs: %s", wp
->llp_lname
,
345 /* Link NCU properties */
346 prop
= NWAM_NCU_PROP_ACTIVATION_MODE
;
347 uintval
= NWAM_ACTIVATION_MODE_PRIORITIZED
;
348 if ((err
= nwamd_set_ncu_uint(phys_ncu
, &uintval
, 1, prop
))
352 prop
= NWAM_NCU_PROP_PRIORITY_MODE
;
353 uintval
= NWAM_PRIORITY_MODE_EXCLUSIVE
;
354 if ((err
= nwamd_set_ncu_uint(phys_ncu
, &uintval
, 1, prop
))
358 prop
= NWAM_NCU_PROP_PRIORITY_GROUP
;
359 uintval
= wp
->llp_pri
;
360 if ((err
= nwamd_set_ncu_uint(phys_ncu
, &uintval
, 1, prop
))
364 /* IP NCU properties */
365 if (wp
->llp_ipv4addrstr
!= NULL
) {
366 /* Set v4 address and specify static addrsrc */
367 prop
= NWAM_NCU_PROP_IPV4_ADDRSRC
;
368 uintval
= NWAM_ADDRSRC_STATIC
;
369 if ((err
= nwamd_set_ncu_uint(ip_ncu
, &uintval
, 1,
370 prop
)) != NWAM_SUCCESS
)
373 prop
= NWAM_NCU_PROP_IPV4_ADDR
;
374 strval
= wp
->llp_ipv4addrstr
;
375 if ((err
= nwamd_set_ncu_string(ip_ncu
, &strval
, 1,
376 prop
)) != NWAM_SUCCESS
)
379 static_configured
= B_TRUE
;
382 if (wp
->llp_ipv6addrstr
!= NULL
) {
383 /* Set v6 address and specify static addrsrc */
384 prop
= NWAM_NCU_PROP_IPV6_ADDRSRC
;
385 uintval
= NWAM_ADDRSRC_STATIC
;
386 if ((err
= nwamd_set_ncu_uint(ip_ncu
, &uintval
, 1,
387 prop
)) != NWAM_SUCCESS
)
390 prop
= NWAM_NCU_PROP_IPV6_ADDR
;
391 strval
= wp
->llp_ipv6addrstr
;
392 if ((err
= nwamd_set_ncu_string(ip_ncu
, &strval
, 1,
393 prop
)) != NWAM_SUCCESS
)
396 static_configured
= B_TRUE
;
399 if (!wp
->llp_ipv6onlink
) {
400 prop
= NWAM_NCU_PROP_IP_VERSION
;
401 uintval
= IPV4_VERSION
;
402 if ((err
= nwamd_set_ncu_uint(ip_ncu
, &uintval
, 1,
403 prop
)) != NWAM_SUCCESS
)
407 if ((err
= nwam_ncu_commit(ip_ncu
, 0)) != NWAM_SUCCESS
||
408 (err
= nwam_ncu_commit(phys_ncu
, 0)) != NWAM_SUCCESS
) {
409 nlog(LOG_ERR
, "upgrade_llp_config: llp %s: "
410 "could not commit NCUs: %s", wp
->llp_lname
,
412 /* Schedule a retry - root filesystem may be readonly */
414 nwam_ncu_free(ip_ncu
);
415 nwam_ncu_free(phys_ncu
);
416 (void) nwam_ncp_destroy(user_ncp
, 0);
421 if (err
!= NWAM_SUCCESS
) {
422 nlog(LOG_ERR
, "upgrade_llp_config: llp %s: "
423 "could not set value for property %s: %s", wp
->llp_lname
,
424 prop
, nwam_strerror(err
));
427 nwam_ncu_free(ip_ncu
);
428 nwam_ncu_free(phys_ncu
);
429 nwam_ncp_free(user_ncp
);
434 * Upgrade legacy llp and known_wifi_nets files. Note - it is possible that
435 * the root filesystem is not writable at this point, so we need to schedule
436 * a retry of the upgrade operation in the event that committing the new
441 nwamd_handle_upgrade(nwamd_event_t event
)
443 nwamd_event_t upgrade_event
;
444 uint64_t dhcp_wait_time
, idle_time
;
445 boolean_t use_net_svc
;
447 switch (upgrade_llp_config()) {
450 /* Nothing readable to upgrade */
454 * Schedule retry in NWAMD_READONLY_RETRY_INTERVAL seconds
455 * as root fs may be readonly.
457 * The upgrade event is of type NCU, but has no associated
458 * object (we use the event type to map to the appropriate
459 * event/method mappings, so to find the NCU upgrade event
460 * method we specify type NCU while not specifying an
461 * object since all NCUs have to be upgraded.
463 upgrade_event
= nwamd_event_init(NWAM_EVENT_TYPE_UPGRADE
,
464 NWAM_OBJECT_TYPE_NCP
, 0, NULL
);
465 if (upgrade_event
== NULL
) {
466 nlog(LOG_ERR
, "nwamd_handle_upgrade: "
467 "could not create retry event to upgrade "
468 "%s configuration", LLPFILE
);
471 nwamd_event_enqueue_timed(upgrade_event
,
472 NWAMD_READONLY_RETRY_INTERVAL
);
479 * If static_configured is set, then at least one static address is
480 * configured in /etc/nwam/llp. Enable the User NCP in this case.
482 if (static_configured
) {
483 nlog(LOG_DEBUG
, "nwamd_handle_upgrade: "
484 "static address configured, enabling User NCP");
485 (void) pthread_mutex_lock(&active_ncp_mutex
);
486 (void) strlcpy(active_ncp
, NWAM_NCP_NAME_USER
,
488 (void) pthread_mutex_unlock(&active_ncp_mutex
);
491 /* upgrade /etc/nwam/known_wifi_nets */
492 upgrade_known_wifi_nets_config();
495 * SMF property nwamd/dhcp_wait_time in Phase 0/0.5 has been
496 * replaced by nwamd/ncu_wait_time property. If the dhcp_wait_time
497 * property exists (which means it has been changed by the user),
498 * set its value to ncu_wait_time and remove the property.
500 if (nwamd_lookup_count_property(OUR_FMRI
, OUR_PG
,
501 OUR_OLD_DHCP_WAIT_TIME_PROP_NAME
, &dhcp_wait_time
) == 0) {
502 (void) nwamd_set_count_property(OUR_FMRI
, OUR_PG
,
503 OUR_NCU_WAIT_TIME_PROP_NAME
, dhcp_wait_time
);
504 (void) nwamd_delete_scf_property(OUR_FMRI
, OUR_PG
,
505 OUR_OLD_DHCP_WAIT_TIME_PROP_NAME
);
506 nlog(LOG_DEBUG
, "nwamd_handle_upgrade: "
507 "converted '%s' to '%s' with value of %lld",
508 OUR_OLD_DHCP_WAIT_TIME_PROP_NAME
,
509 OUR_NCU_WAIT_TIME_PROP_NAME
, dhcp_wait_time
);
513 * If the user has changed Phase 0/0.5 properties that don't exist in
514 * Phase 1, manifest-import reports a warning; but those properties are
515 * not removed. nwamd/use_net_svc and nwamd/idle_time are two
516 * properties that don't exist in Phase 1. If they exist, remove them.
518 if (nwamd_lookup_count_property(OUR_FMRI
, OUR_PG
,
519 OUR_OLD_IDLE_TIME_PROP_NAME
, &idle_time
) == 0) {
520 (void) nwamd_delete_scf_property(OUR_FMRI
, OUR_PG
,
521 OUR_OLD_IDLE_TIME_PROP_NAME
);
523 if (nwamd_lookup_boolean_property(OUR_FMRI
, OUR_PG
,
524 OUR_OLD_USE_NET_SVC_PROP_NAME
, &use_net_svc
) == 0) {
525 (void) nwamd_delete_scf_property(OUR_FMRI
, OUR_PG
,
526 OUR_OLD_USE_NET_SVC_PROP_NAME
);
529 nlog(LOG_DEBUG
, "nwamd_handle_upgrade: "
530 "creating version property, setting to 1\n");
531 (void) nwamd_set_count_property(OUR_FMRI
, OUR_PG
,
532 OUR_VERSION_PROP_NAME
, 1U);
533 (void) smf_refresh_instance(OUR_FMRI
);