xref: /onnv-gate/usr/src/cmd/cmd-inet/lib/nwamd/llp.c (revision 12371:dd3a3f0b2318)
13938Sjbeck /*
23938Sjbeck  * CDDL HEADER START
33938Sjbeck  *
43938Sjbeck  * The contents of this file are subject to the terms of the
53938Sjbeck  * Common Development and Distribution License (the "License").
63938Sjbeck  * You may not use this file except in compliance with the License.
73938Sjbeck  *
83938Sjbeck  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93938Sjbeck  * or http://www.opensolaris.org/os/licensing.
103938Sjbeck  * See the License for the specific language governing permissions
113938Sjbeck  * and limitations under the License.
123938Sjbeck  *
133938Sjbeck  * When distributing Covered Code, include this CDDL HEADER in each
143938Sjbeck  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153938Sjbeck  * If applicable, add the following below this CDDL HEADER, with the
163938Sjbeck  * fields enclosed by brackets "[]" replaced with your own identifying
173938Sjbeck  * information: Portions Copyright [yyyy] [name of copyright owner]
183938Sjbeck  *
193938Sjbeck  * CDDL HEADER END
203938Sjbeck  */
213938Sjbeck 
223938Sjbeck /*
23*12371SAnurag.Maskey@Oracle.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
243938Sjbeck  */
253938Sjbeck 
263938Sjbeck /*
2711767SAnurag.Maskey@Sun.COM  * This file is here for legacy support.
283938Sjbeck  */
293938Sjbeck 
3011767SAnurag.Maskey@Sun.COM #include <atomic.h>
313938Sjbeck #include <ctype.h>
323938Sjbeck #include <errno.h>
3311767SAnurag.Maskey@Sun.COM #include <limits.h>
3411767SAnurag.Maskey@Sun.COM #include <libdllink.h>
3511767SAnurag.Maskey@Sun.COM #include <libscf.h>
3611767SAnurag.Maskey@Sun.COM #include <stdio.h>
3711767SAnurag.Maskey@Sun.COM #include <stdlib.h>
3811767SAnurag.Maskey@Sun.COM #include <string.h>
3911767SAnurag.Maskey@Sun.COM #include <strings.h>
403938Sjbeck 
4111767SAnurag.Maskey@Sun.COM #include <libnwam.h>
4211767SAnurag.Maskey@Sun.COM #include "known_wlans.h"
4311767SAnurag.Maskey@Sun.COM #include "llp.h"
4411767SAnurag.Maskey@Sun.COM #include "ncu.h"
4511767SAnurag.Maskey@Sun.COM #include "util.h"
463938Sjbeck 
4711767SAnurag.Maskey@Sun.COM /*
4811767SAnurag.Maskey@Sun.COM  * This file formerly contained the routines that manipulate Link Layer
4911767SAnurag.Maskey@Sun.COM  * Profiles (aka LLPs) and various support functions.  Now only code
5011767SAnurag.Maskey@Sun.COM  * necessary for parsing the legacy /etc/nwam/llp file on upgrade is included,
5111767SAnurag.Maskey@Sun.COM  * since this legacy configuration needs to be translated into the User NCP.
5211767SAnurag.Maskey@Sun.COM  */
533938Sjbeck 
5411767SAnurag.Maskey@Sun.COM #define	OUR_OLD_DHCP_WAIT_TIME_PROP_NAME	"dhcp_wait_time"
5511767SAnurag.Maskey@Sun.COM #define	OUR_OLD_USE_NET_SVC_PROP_NAME		"use_net_svc"
5611767SAnurag.Maskey@Sun.COM #define	OUR_OLD_IDLE_TIME_PROP_NAME		"idle_time"
577645Sjames.d.carlson@sun.com 
587645Sjames.d.carlson@sun.com static struct qelem llp_list;
593938Sjbeck 
603938Sjbeck /*
613938Sjbeck  * Global variable to hold the highest priority.  Need to use the atomic
623938Sjbeck  * integer arithmetic functions to update it.
633938Sjbeck  */
647645Sjames.d.carlson@sun.com static uint32_t llp_highest_pri;
653938Sjbeck 
6611767SAnurag.Maskey@Sun.COM /* Specifies if static address has been configured in /etc/nwam/llp */
6711767SAnurag.Maskey@Sun.COM static boolean_t static_configured = B_FALSE;
6811767SAnurag.Maskey@Sun.COM 
6911767SAnurag.Maskey@Sun.COM static enum interface_type
find_if_type(const char * name)7011767SAnurag.Maskey@Sun.COM find_if_type(const char *name)
7111767SAnurag.Maskey@Sun.COM {
7211767SAnurag.Maskey@Sun.COM 	uint32_t media;
7311767SAnurag.Maskey@Sun.COM 	enum interface_type type;
7411767SAnurag.Maskey@Sun.COM 
7511767SAnurag.Maskey@Sun.COM 	if (name == NULL) {
7611767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "find_if_type: no ifname; "
7711767SAnurag.Maskey@Sun.COM 		    "returning IF_UNKNOWN");
7811767SAnurag.Maskey@Sun.COM 		return (IF_UNKNOWN);
7911767SAnurag.Maskey@Sun.COM 	}
803938Sjbeck 
8111767SAnurag.Maskey@Sun.COM 	type = IF_WIRED;
8211767SAnurag.Maskey@Sun.COM 	if (dladm_name2info(dld_handle, name, NULL, NULL, NULL, &media) !=
8311767SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
8411767SAnurag.Maskey@Sun.COM 		if (strncmp(name, "ip.tun", 6) == 0 ||
8511767SAnurag.Maskey@Sun.COM 		    strncmp(name, "ip6.tun", 7) == 0 ||
8611767SAnurag.Maskey@Sun.COM 		    strncmp(name, "ip.6to4tun", 10) == 0)
8711767SAnurag.Maskey@Sun.COM 			/*
8811767SAnurag.Maskey@Sun.COM 			 * We'll need to update our tunnel detection once
8911767SAnurag.Maskey@Sun.COM 			 * the clearview/tun project is integrated; tunnel
9011767SAnurag.Maskey@Sun.COM 			 * names won't necessarily be ip.tunN.
9111767SAnurag.Maskey@Sun.COM 			 */
9211767SAnurag.Maskey@Sun.COM 			type = IF_TUN;
9311767SAnurag.Maskey@Sun.COM 	} else if (media == DL_WIFI) {
9411767SAnurag.Maskey@Sun.COM 		type = IF_WIRELESS;
9511767SAnurag.Maskey@Sun.COM 	}
9611767SAnurag.Maskey@Sun.COM 
9711767SAnurag.Maskey@Sun.COM 	return (type);
987645Sjames.d.carlson@sun.com }
997645Sjames.d.carlson@sun.com 
10011767SAnurag.Maskey@Sun.COM static void
llp_list_free(void)10111767SAnurag.Maskey@Sun.COM llp_list_free(void)
1023938Sjbeck {
10311767SAnurag.Maskey@Sun.COM 	llp_t *llp;
1043938Sjbeck 
10511767SAnurag.Maskey@Sun.COM 	while (llp_list.q_forw != &llp_list) {
10611767SAnurag.Maskey@Sun.COM 		llp = (llp_t *)llp_list.q_forw;
1077645Sjames.d.carlson@sun.com 		remque(&llp->llp_links);
1087645Sjames.d.carlson@sun.com 		free(llp->llp_ipv6addrstr);
1097645Sjames.d.carlson@sun.com 		free(llp->llp_ipv4addrstr);
1107645Sjames.d.carlson@sun.com 		free(llp);
1117645Sjames.d.carlson@sun.com 	}
1127645Sjames.d.carlson@sun.com }
1133938Sjbeck 
1147645Sjames.d.carlson@sun.com static void
initialize_llp(void)11511767SAnurag.Maskey@Sun.COM initialize_llp(void)
1167645Sjames.d.carlson@sun.com {
11711767SAnurag.Maskey@Sun.COM 	llp_list.q_forw = llp_list.q_back = &llp_list;
1183938Sjbeck }
1193938Sjbeck 
12011767SAnurag.Maskey@Sun.COM static llp_t *
llp_lookup(const char * link)1213938Sjbeck llp_lookup(const char *link)
1223938Sjbeck {
1233938Sjbeck 	llp_t *llp;
1243938Sjbeck 
1253938Sjbeck 	if (link == NULL)
1263938Sjbeck 		return (NULL);
1273938Sjbeck 
1287645Sjames.d.carlson@sun.com 	for (llp = (llp_t *)llp_list.q_forw; llp != (llp_t *)&llp_list;
1297645Sjames.d.carlson@sun.com 	    llp = (llp_t *)llp->llp_links.q_forw) {
1303938Sjbeck 		if (strcmp(link, llp->llp_lname) == 0)
1313938Sjbeck 			break;
1323938Sjbeck 	}
1337645Sjames.d.carlson@sun.com 	if (llp == (llp_t *)&llp_list)
1347645Sjames.d.carlson@sun.com 		llp = NULL;
1353938Sjbeck 	return (llp);
1363938Sjbeck }
1373938Sjbeck 
1383938Sjbeck /*
1397645Sjames.d.carlson@sun.com  * Create the named LLP with default settings.  Called only in main thread.
1403938Sjbeck  */
14111767SAnurag.Maskey@Sun.COM static llp_t *
llp_add(const char * name)1427645Sjames.d.carlson@sun.com llp_add(const char *name)
1433938Sjbeck {
1447645Sjames.d.carlson@sun.com 	llp_t *llp;
1453938Sjbeck 
1467645Sjames.d.carlson@sun.com 	if ((llp = calloc(1, sizeof (llp_t))) == NULL) {
14711767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "llp_add: cannot allocate LLP: %m");
1487645Sjames.d.carlson@sun.com 		return (NULL);
1497645Sjames.d.carlson@sun.com 	}
1503938Sjbeck 
1517645Sjames.d.carlson@sun.com 	if (strlcpy(llp->llp_lname, name, sizeof (llp->llp_lname)) >=
1527645Sjames.d.carlson@sun.com 	    sizeof (llp->llp_lname)) {
15311767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "llp_add: linkname '%s' too long; ignoring entry",
1547645Sjames.d.carlson@sun.com 		    name);
1557645Sjames.d.carlson@sun.com 		free(llp);
1567645Sjames.d.carlson@sun.com 		return (NULL);
1573938Sjbeck 	}
1583938Sjbeck 
1597645Sjames.d.carlson@sun.com 	llp->llp_fileorder = llp->llp_pri =
1607645Sjames.d.carlson@sun.com 	    atomic_add_32_nv(&llp_highest_pri, 1);
1617645Sjames.d.carlson@sun.com 	llp->llp_ipv4src = IPV4SRC_DHCP;
1627645Sjames.d.carlson@sun.com 	llp->llp_type = find_if_type(llp->llp_lname);
1637645Sjames.d.carlson@sun.com 	llp->llp_ipv6onlink = B_TRUE;
1643938Sjbeck 
1653938Sjbeck 	/*
1663938Sjbeck 	 * should be a no-op, but for now, make sure we only
1673938Sjbeck 	 * create llps for wired and wireless interfaces.
1683938Sjbeck 	 */
1697645Sjames.d.carlson@sun.com 	if (llp->llp_type != IF_WIRED && llp->llp_type != IF_WIRELESS) {
17011767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "llp_add: wrong type of interface for %s", name);
1717645Sjames.d.carlson@sun.com 		free(llp);
1727645Sjames.d.carlson@sun.com 		return (NULL);
1733938Sjbeck 	}
1747645Sjames.d.carlson@sun.com 	insque(&llp->llp_links, llp_list.q_back);
1753938Sjbeck 
17611767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "llp_add: "
17711767SAnurag.Maskey@Sun.COM 	    "created llp for link %s, priority %d", llp->llp_lname,
1787645Sjames.d.carlson@sun.com 	    llp->llp_pri);
1797645Sjames.d.carlson@sun.com 	return (llp);
1803938Sjbeck }
1813938Sjbeck 
18211767SAnurag.Maskey@Sun.COM static int
parse_llp_config(void)18311767SAnurag.Maskey@Sun.COM parse_llp_config(void)
1843938Sjbeck {
1853938Sjbeck 	static const char STATICSTR[] = "static";
1863938Sjbeck 	static const char DHCP[] = "dhcp";
1873938Sjbeck 	static const char IPV6[] = "ipv6";
1883938Sjbeck 	static const char NOIPV6[] = "noipv6";
1897645Sjames.d.carlson@sun.com 	static const char PRIORITY[] = "priority";
1903938Sjbeck 	FILE *fp;
1913938Sjbeck 	char line[LINE_MAX];
1927645Sjames.d.carlson@sun.com 	char *cp, *lasts, *lstr, *srcstr, *addrstr;
1933938Sjbeck 	int lnum;
1947645Sjames.d.carlson@sun.com 	llp_t *llp;
1957645Sjames.d.carlson@sun.com 
19611767SAnurag.Maskey@Sun.COM 	initialize_llp();
1973938Sjbeck 
1983938Sjbeck 	fp = fopen(LLPFILE, "r+");
1993938Sjbeck 	if (fp == NULL) {
20011767SAnurag.Maskey@Sun.COM 		if (errno == ENOENT)
20111767SAnurag.Maskey@Sun.COM 			return (errno);
20211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "parse_llp_config: "
20311767SAnurag.Maskey@Sun.COM 		    "open legacy LLP config file: %m");
20411767SAnurag.Maskey@Sun.COM 		return (-1);
2053938Sjbeck 	}
2063938Sjbeck 
2073938Sjbeck 	for (lnum = 1; fgets(line, sizeof (line), fp) != NULL; lnum++) {
2083938Sjbeck 		if (line[strlen(line) - 1] == '\n')
2093938Sjbeck 			line[strlen(line) - 1] = '\0';
2103938Sjbeck 
2113938Sjbeck 		cp = line;
2123938Sjbeck 		while (isspace(*cp))
2133938Sjbeck 			cp++;
2143938Sjbeck 
2153938Sjbeck 		if (*cp == '#' || *cp == '\0')
2163938Sjbeck 			continue;
2173938Sjbeck 
21811767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "parse_llp_config: "
21911767SAnurag.Maskey@Sun.COM 		    "parsing legacy LLP conf file line %d...", lnum);
2203938Sjbeck 
2213938Sjbeck 		if (((lstr = strtok_r(cp, " \t", &lasts)) == NULL) ||
2223938Sjbeck 		    ((srcstr = strtok_r(NULL, " \t", &lasts)) == NULL)) {
22311767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "parse_llp_config: line %d: "
22411767SAnurag.Maskey@Sun.COM 			    "not enough tokens; ignoring entry", lnum);
2253938Sjbeck 			continue;
2263938Sjbeck 		}
2277645Sjames.d.carlson@sun.com 
2287645Sjames.d.carlson@sun.com 		if ((llp = llp_lookup(lstr)) == NULL &&
2297645Sjames.d.carlson@sun.com 		    (llp = llp_add(lstr)) == NULL) {
23011767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "parse_llp_config: line %d: "
23111767SAnurag.Maskey@Sun.COM 			    "cannot add entry", lnum);
2327645Sjames.d.carlson@sun.com 			continue;
2337645Sjames.d.carlson@sun.com 		}
2347645Sjames.d.carlson@sun.com 
2353938Sjbeck 		if (strcasecmp(srcstr, STATICSTR) == 0) {
2363938Sjbeck 			if ((addrstr = strtok_r(NULL, " \t", &lasts)) == NULL ||
2373938Sjbeck 			    atoi(addrstr) == 0) { /* crude check for number */
23811767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "parse_llp_config: line %d: "
23911767SAnurag.Maskey@Sun.COM 				    "missing ipaddr for static config", lnum);
2407645Sjames.d.carlson@sun.com 			} else if ((addrstr = strdup(addrstr)) == NULL) {
24111767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "parse_llp_config: line %d: "
24211767SAnurag.Maskey@Sun.COM 				    "cannot save address", lnum);
2437645Sjames.d.carlson@sun.com 			} else {
2447645Sjames.d.carlson@sun.com 				free(llp->llp_ipv4addrstr);
2457645Sjames.d.carlson@sun.com 				llp->llp_ipv4src = IPV4SRC_STATIC;
2467645Sjames.d.carlson@sun.com 				llp->llp_ipv4addrstr = addrstr;
2473938Sjbeck 			}
2487645Sjames.d.carlson@sun.com 
2493938Sjbeck 		} else if (strcasecmp(srcstr, DHCP) == 0) {
2507645Sjames.d.carlson@sun.com 			llp->llp_ipv4src = IPV4SRC_DHCP;
2517645Sjames.d.carlson@sun.com 
2523938Sjbeck 		} else if (strcasecmp(srcstr, IPV6) == 0) {
2537645Sjames.d.carlson@sun.com 			llp->llp_ipv6onlink = B_TRUE;
2547645Sjames.d.carlson@sun.com 			if ((addrstr = strtok_r(NULL, " \t", &lasts)) == NULL) {
2557645Sjames.d.carlson@sun.com 				(void) 0;
2567645Sjames.d.carlson@sun.com 			} else if ((addrstr = strdup(addrstr)) == NULL) {
25711767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR, "parse_llp_config: line %d: "
25811767SAnurag.Maskey@Sun.COM 				    "cannot save address", lnum);
2593938Sjbeck 			} else {
2607645Sjames.d.carlson@sun.com 				free(llp->llp_ipv6addrstr);
2617645Sjames.d.carlson@sun.com 				llp->llp_ipv6addrstr = addrstr;
2623938Sjbeck 			}
2637645Sjames.d.carlson@sun.com 
2643938Sjbeck 		} else if (strcasecmp(srcstr, NOIPV6) == 0) {
2657645Sjames.d.carlson@sun.com 			llp->llp_ipv6onlink = B_FALSE;
2667645Sjames.d.carlson@sun.com 
2677645Sjames.d.carlson@sun.com 		} else if (strcasecmp(srcstr, PRIORITY) == 0) {
2687645Sjames.d.carlson@sun.com 			if ((addrstr = strtok_r(NULL, " \t", &lasts)) == NULL) {
26911767SAnurag.Maskey@Sun.COM 				nlog(LOG_ERR,
27011767SAnurag.Maskey@Sun.COM 				    "parse_llp_config: line %d: "
27111767SAnurag.Maskey@Sun.COM 				    "missing priority value", lnum);
2727645Sjames.d.carlson@sun.com 			} else {
2737645Sjames.d.carlson@sun.com 				llp->llp_pri = atoi(addrstr);
2747645Sjames.d.carlson@sun.com 			}
2757645Sjames.d.carlson@sun.com 
2763938Sjbeck 		} else {
27711767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "parse_llp_config: line %d: "
27811767SAnurag.Maskey@Sun.COM 			    "unrecognized field '%s'", lnum, srcstr);
2793938Sjbeck 		}
2803938Sjbeck 	}
2813938Sjbeck 
2823938Sjbeck 	(void) fclose(fp);
28311767SAnurag.Maskey@Sun.COM 	return (0);
2847645Sjames.d.carlson@sun.com }
2857645Sjames.d.carlson@sun.com 
2867645Sjames.d.carlson@sun.com /*
28711767SAnurag.Maskey@Sun.COM  * Translate legacy LLP config into the user NCP.
2887645Sjames.d.carlson@sun.com  */
28911767SAnurag.Maskey@Sun.COM static int
upgrade_llp_config(void)29011767SAnurag.Maskey@Sun.COM upgrade_llp_config(void)
2917645Sjames.d.carlson@sun.com {
29211767SAnurag.Maskey@Sun.COM 	llp_t *wp;
29311767SAnurag.Maskey@Sun.COM 	nwam_ncp_handle_t user_ncp;
29411767SAnurag.Maskey@Sun.COM 	nwam_ncu_handle_t phys_ncu = NULL, ip_ncu = NULL;
29511767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
29611767SAnurag.Maskey@Sun.COM 	uint64_t uintval;
29711767SAnurag.Maskey@Sun.COM 	char *strval;
29811767SAnurag.Maskey@Sun.COM 	const char *prop;
2997645Sjames.d.carlson@sun.com 
30011767SAnurag.Maskey@Sun.COM 	switch (parse_llp_config()) {
30111767SAnurag.Maskey@Sun.COM 	case -1:
30211767SAnurag.Maskey@Sun.COM 		return (0);
30311767SAnurag.Maskey@Sun.COM 	case ENOENT:
30411767SAnurag.Maskey@Sun.COM 		return (ENOENT);
30511767SAnurag.Maskey@Sun.COM 	default:
30611767SAnurag.Maskey@Sun.COM 		break;
30711767SAnurag.Maskey@Sun.COM 	}
308*12371SAnurag.Maskey@Oracle.COM 
309*12371SAnurag.Maskey@Oracle.COM 	err = nwam_ncp_create(NWAM_NCP_NAME_USER, 0, &user_ncp);
310*12371SAnurag.Maskey@Oracle.COM 	switch (err) {
311*12371SAnurag.Maskey@Oracle.COM 	case NWAM_SUCCESS:
312*12371SAnurag.Maskey@Oracle.COM 		break;
313*12371SAnurag.Maskey@Oracle.COM 	case NWAM_ERROR_BIND:
314*12371SAnurag.Maskey@Oracle.COM 	case NWAM_ERROR_INTERNAL:
31511767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "upgrade_llp_config: "
316*12371SAnurag.Maskey@Oracle.COM 		    "could not create User NCP: %s", nwam_strerror(err));
317*12371SAnurag.Maskey@Oracle.COM 		llp_list_free();
318*12371SAnurag.Maskey@Oracle.COM 		return (EAGAIN);
319*12371SAnurag.Maskey@Oracle.COM 	default:
320*12371SAnurag.Maskey@Oracle.COM 		nlog(LOG_ERR, "upgrade_llp_config: error creating User NCP: %s",
321*12371SAnurag.Maskey@Oracle.COM 		    nwam_strerror(err));
32211767SAnurag.Maskey@Sun.COM 		llp_list_free();
32311767SAnurag.Maskey@Sun.COM 		return (0);
3247645Sjames.d.carlson@sun.com 	}
32511767SAnurag.Maskey@Sun.COM 
32611767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "upgrade_llp_config: walking llp list");
32711767SAnurag.Maskey@Sun.COM 
32811767SAnurag.Maskey@Sun.COM 	for (wp = (llp_t *)llp_list.q_forw; wp != (llp_t *)&llp_list;
32911767SAnurag.Maskey@Sun.COM 	    wp = (llp_t *)wp->llp_links.q_forw) {
33011767SAnurag.Maskey@Sun.COM 
33111767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "upgrade_llp_config: "
33211767SAnurag.Maskey@Sun.COM 		    "upgrading llp %s", wp->llp_lname);
3337645Sjames.d.carlson@sun.com 
33411767SAnurag.Maskey@Sun.COM 		if (nwam_ncu_create(user_ncp, wp->llp_lname,
33511767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_TYPE_INTERFACE, NWAM_NCU_CLASS_IP, &ip_ncu)
33611767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS ||
33711767SAnurag.Maskey@Sun.COM 		    nwam_ncu_create(user_ncp, wp->llp_lname, NWAM_NCU_TYPE_LINK,
33811767SAnurag.Maskey@Sun.COM 		    NWAM_NCU_CLASS_PHYS, &phys_ncu) != NWAM_SUCCESS) {
33911767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "upgrade_llp_config: llp %s: "
34011767SAnurag.Maskey@Sun.COM 			    "could not create NCUs: %s", wp->llp_lname,
34111767SAnurag.Maskey@Sun.COM 			    nwam_strerror(err));
34211767SAnurag.Maskey@Sun.COM 			break;
34311767SAnurag.Maskey@Sun.COM 		}
3447645Sjames.d.carlson@sun.com 
34511767SAnurag.Maskey@Sun.COM 		/* Link NCU properties */
34611767SAnurag.Maskey@Sun.COM 		prop = NWAM_NCU_PROP_ACTIVATION_MODE;
34711767SAnurag.Maskey@Sun.COM 		uintval = NWAM_ACTIVATION_MODE_PRIORITIZED;
34811767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_set_ncu_uint(phys_ncu, &uintval, 1, prop))
34911767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS)
35011767SAnurag.Maskey@Sun.COM 			break;
35111767SAnurag.Maskey@Sun.COM 
35211767SAnurag.Maskey@Sun.COM 		prop = NWAM_NCU_PROP_PRIORITY_MODE;
35311767SAnurag.Maskey@Sun.COM 		uintval = NWAM_PRIORITY_MODE_EXCLUSIVE;
35411767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_set_ncu_uint(phys_ncu, &uintval, 1, prop))
35511767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS)
35611767SAnurag.Maskey@Sun.COM 			break;
35711767SAnurag.Maskey@Sun.COM 
35811767SAnurag.Maskey@Sun.COM 		prop = NWAM_NCU_PROP_PRIORITY_GROUP;
35911767SAnurag.Maskey@Sun.COM 		uintval = wp->llp_pri;
36011767SAnurag.Maskey@Sun.COM 		if ((err = nwamd_set_ncu_uint(phys_ncu, &uintval, 1, prop))
36111767SAnurag.Maskey@Sun.COM 		    != NWAM_SUCCESS)
36211767SAnurag.Maskey@Sun.COM 			break;
3637645Sjames.d.carlson@sun.com 
36411767SAnurag.Maskey@Sun.COM 		/* IP NCU properties */
36511767SAnurag.Maskey@Sun.COM 		if (wp->llp_ipv4addrstr != NULL) {
36611767SAnurag.Maskey@Sun.COM 			/* Set v4 address and specify static addrsrc */
36711767SAnurag.Maskey@Sun.COM 			prop = NWAM_NCU_PROP_IPV4_ADDRSRC;
36811767SAnurag.Maskey@Sun.COM 			uintval = NWAM_ADDRSRC_STATIC;
36911767SAnurag.Maskey@Sun.COM 			if ((err = nwamd_set_ncu_uint(ip_ncu, &uintval, 1,
37011767SAnurag.Maskey@Sun.COM 			    prop)) != NWAM_SUCCESS)
37111767SAnurag.Maskey@Sun.COM 				break;
37211767SAnurag.Maskey@Sun.COM 
37311767SAnurag.Maskey@Sun.COM 			prop = NWAM_NCU_PROP_IPV4_ADDR;
37411767SAnurag.Maskey@Sun.COM 			strval = wp->llp_ipv4addrstr;
37511767SAnurag.Maskey@Sun.COM 			if ((err = nwamd_set_ncu_string(ip_ncu, &strval, 1,
37611767SAnurag.Maskey@Sun.COM 			    prop)) != NWAM_SUCCESS)
37711767SAnurag.Maskey@Sun.COM 				break;
37811767SAnurag.Maskey@Sun.COM 
37911767SAnurag.Maskey@Sun.COM 			static_configured = B_TRUE;
38011767SAnurag.Maskey@Sun.COM 		}
38111767SAnurag.Maskey@Sun.COM 
38211767SAnurag.Maskey@Sun.COM 		if (wp->llp_ipv6addrstr != NULL) {
38311767SAnurag.Maskey@Sun.COM 			/* Set v6 address and specify static addrsrc */
38411767SAnurag.Maskey@Sun.COM 			prop = NWAM_NCU_PROP_IPV6_ADDRSRC;
38511767SAnurag.Maskey@Sun.COM 			uintval = NWAM_ADDRSRC_STATIC;
38611767SAnurag.Maskey@Sun.COM 			if ((err = nwamd_set_ncu_uint(ip_ncu, &uintval, 1,
38711767SAnurag.Maskey@Sun.COM 			    prop)) != NWAM_SUCCESS)
38811767SAnurag.Maskey@Sun.COM 				break;
38911767SAnurag.Maskey@Sun.COM 
39011767SAnurag.Maskey@Sun.COM 			prop = NWAM_NCU_PROP_IPV6_ADDR;
39111767SAnurag.Maskey@Sun.COM 			strval = wp->llp_ipv6addrstr;
39211767SAnurag.Maskey@Sun.COM 			if ((err = nwamd_set_ncu_string(ip_ncu, &strval, 1,
39311767SAnurag.Maskey@Sun.COM 			    prop)) != NWAM_SUCCESS)
39411767SAnurag.Maskey@Sun.COM 				break;
39511767SAnurag.Maskey@Sun.COM 
39611767SAnurag.Maskey@Sun.COM 			static_configured = B_TRUE;
39711767SAnurag.Maskey@Sun.COM 		}
39811767SAnurag.Maskey@Sun.COM 
39911767SAnurag.Maskey@Sun.COM 		if (!wp->llp_ipv6onlink) {
40011767SAnurag.Maskey@Sun.COM 			prop = NWAM_NCU_PROP_IP_VERSION;
40111767SAnurag.Maskey@Sun.COM 			uintval = IPV4_VERSION;
40211767SAnurag.Maskey@Sun.COM 			if ((err = nwamd_set_ncu_uint(ip_ncu, &uintval, 1,
40311767SAnurag.Maskey@Sun.COM 			    prop)) != NWAM_SUCCESS)
40411767SAnurag.Maskey@Sun.COM 				break;
40511767SAnurag.Maskey@Sun.COM 		}
40611767SAnurag.Maskey@Sun.COM 
40711767SAnurag.Maskey@Sun.COM 		if ((err = nwam_ncu_commit(ip_ncu, 0)) != NWAM_SUCCESS ||
40811767SAnurag.Maskey@Sun.COM 		    (err = nwam_ncu_commit(phys_ncu, 0)) != NWAM_SUCCESS) {
40911767SAnurag.Maskey@Sun.COM 			nlog(LOG_ERR, "upgrade_llp_config: llp %s: "
41011767SAnurag.Maskey@Sun.COM 			    "could not commit NCUs: %s", wp->llp_lname,
41111767SAnurag.Maskey@Sun.COM 			    nwam_strerror(err));
41211767SAnurag.Maskey@Sun.COM 			/* Schedule a retry - root filesystem may be readonly */
41311767SAnurag.Maskey@Sun.COM 			llp_list_free();
414*12371SAnurag.Maskey@Oracle.COM 			nwam_ncu_free(ip_ncu);
415*12371SAnurag.Maskey@Oracle.COM 			nwam_ncu_free(phys_ncu);
416*12371SAnurag.Maskey@Oracle.COM 			(void) nwam_ncp_destroy(user_ncp, 0);
41711767SAnurag.Maskey@Sun.COM 			return (EAGAIN);
41811767SAnurag.Maskey@Sun.COM 		}
4197645Sjames.d.carlson@sun.com 	}
42011767SAnurag.Maskey@Sun.COM 
42111767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS) {
42211767SAnurag.Maskey@Sun.COM 		nlog(LOG_ERR, "upgrade_llp_config: llp %s: "
42311767SAnurag.Maskey@Sun.COM 		    "could not set value for property %s: %s", wp->llp_lname,
42411767SAnurag.Maskey@Sun.COM 		    prop, nwam_strerror(err));
4257645Sjames.d.carlson@sun.com 	}
42611767SAnurag.Maskey@Sun.COM 	llp_list_free();
427*12371SAnurag.Maskey@Oracle.COM 	nwam_ncu_free(ip_ncu);
428*12371SAnurag.Maskey@Oracle.COM 	nwam_ncu_free(phys_ncu);
429*12371SAnurag.Maskey@Oracle.COM 	nwam_ncp_free(user_ncp);
43011767SAnurag.Maskey@Sun.COM 	return (0);
4317645Sjames.d.carlson@sun.com }
4327645Sjames.d.carlson@sun.com 
4337645Sjames.d.carlson@sun.com /*
43411767SAnurag.Maskey@Sun.COM  * Upgrade legacy llp and known_wifi_nets files. Note - it is possible that
43511767SAnurag.Maskey@Sun.COM  * the root filesystem is not writable at this point, so we need to schedule
43611767SAnurag.Maskey@Sun.COM  * a retry of the upgrade operation in the event that committing the new
43711767SAnurag.Maskey@Sun.COM  * config fails.
4387645Sjames.d.carlson@sun.com  */
43911767SAnurag.Maskey@Sun.COM /* ARGSUSED0 */
4407645Sjames.d.carlson@sun.com void
nwamd_handle_upgrade(nwamd_event_t event)44111767SAnurag.Maskey@Sun.COM nwamd_handle_upgrade(nwamd_event_t event)
4427645Sjames.d.carlson@sun.com {
44311767SAnurag.Maskey@Sun.COM 	nwamd_event_t upgrade_event;
44411767SAnurag.Maskey@Sun.COM 	uint64_t dhcp_wait_time, idle_time;
44511767SAnurag.Maskey@Sun.COM 	boolean_t use_net_svc;
44611767SAnurag.Maskey@Sun.COM 
44711767SAnurag.Maskey@Sun.COM 	switch (upgrade_llp_config()) {
44811767SAnurag.Maskey@Sun.COM 	case -1:
44911767SAnurag.Maskey@Sun.COM 	case ENOENT:
45011767SAnurag.Maskey@Sun.COM 		/* Nothing readable to upgrade */
45111767SAnurag.Maskey@Sun.COM 		break;
45211767SAnurag.Maskey@Sun.COM 	case EAGAIN:
45311767SAnurag.Maskey@Sun.COM 		/*
45411767SAnurag.Maskey@Sun.COM 		 * Schedule retry in NWAMD_READONLY_RETRY_INTERVAL seconds
45511767SAnurag.Maskey@Sun.COM 		 * as root fs may be readonly.
45611767SAnurag.Maskey@Sun.COM 		 *
45711767SAnurag.Maskey@Sun.COM 		 * The upgrade event is of type NCU, but has no associated
45811767SAnurag.Maskey@Sun.COM 		 * object (we use the event type to map to the appropriate
45911767SAnurag.Maskey@Sun.COM 		 * event/method mappings, so to find the NCU upgrade event
46011767SAnurag.Maskey@Sun.COM 		 * method we specify type NCU while not specifying an
46111767SAnurag.Maskey@Sun.COM 		 * object since all NCUs have to be upgraded.
46211767SAnurag.Maskey@Sun.COM 		 */
46311767SAnurag.Maskey@Sun.COM 		upgrade_event = nwamd_event_init(NWAM_EVENT_TYPE_UPGRADE,
46411767SAnurag.Maskey@Sun.COM 		    NWAM_OBJECT_TYPE_NCP, 0, NULL);
465*12371SAnurag.Maskey@Oracle.COM 		if (upgrade_event == NULL) {
466*12371SAnurag.Maskey@Oracle.COM 			nlog(LOG_ERR, "nwamd_handle_upgrade: "
467*12371SAnurag.Maskey@Oracle.COM 			    "could not create retry event to upgrade "
468*12371SAnurag.Maskey@Oracle.COM 			    "%s configuration", LLPFILE);
46911767SAnurag.Maskey@Sun.COM 			return;
470*12371SAnurag.Maskey@Oracle.COM 		}
47111767SAnurag.Maskey@Sun.COM 		nwamd_event_enqueue_timed(upgrade_event,
47211767SAnurag.Maskey@Sun.COM 		    NWAMD_READONLY_RETRY_INTERVAL);
47311767SAnurag.Maskey@Sun.COM 		return;
47411767SAnurag.Maskey@Sun.COM 	default:
47511767SAnurag.Maskey@Sun.COM 		break;
47611767SAnurag.Maskey@Sun.COM 	}
4777645Sjames.d.carlson@sun.com 
4787645Sjames.d.carlson@sun.com 	/*
47911767SAnurag.Maskey@Sun.COM 	 * If static_configured is set, then at least one static address is
48011767SAnurag.Maskey@Sun.COM 	 * configured in /etc/nwam/llp.  Enable the User NCP in this case.
4817645Sjames.d.carlson@sun.com 	 */
48211767SAnurag.Maskey@Sun.COM 	if (static_configured) {
48311767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_handle_upgrade: "
48411767SAnurag.Maskey@Sun.COM 		    "static address configured, enabling User NCP");
48511767SAnurag.Maskey@Sun.COM 		(void) pthread_mutex_lock(&active_ncp_mutex);
48611767SAnurag.Maskey@Sun.COM 		(void) strlcpy(active_ncp, NWAM_NCP_NAME_USER,
48711767SAnurag.Maskey@Sun.COM 		    NWAM_MAX_NAME_LEN);
48811767SAnurag.Maskey@Sun.COM 		(void) pthread_mutex_unlock(&active_ncp_mutex);
48911767SAnurag.Maskey@Sun.COM 	}
4907645Sjames.d.carlson@sun.com 
49111767SAnurag.Maskey@Sun.COM 	/* upgrade /etc/nwam/known_wifi_nets */
49211767SAnurag.Maskey@Sun.COM 	upgrade_known_wifi_nets_config();
4937645Sjames.d.carlson@sun.com 
49411767SAnurag.Maskey@Sun.COM 	/*
49511767SAnurag.Maskey@Sun.COM 	 * SMF property nwamd/dhcp_wait_time in Phase 0/0.5 has been
49611767SAnurag.Maskey@Sun.COM 	 * replaced by nwamd/ncu_wait_time property.  If the dhcp_wait_time
49711767SAnurag.Maskey@Sun.COM 	 * property exists (which means it has been changed by the user),
49811767SAnurag.Maskey@Sun.COM 	 * set its value to ncu_wait_time and remove the property.
49911767SAnurag.Maskey@Sun.COM 	 */
50011767SAnurag.Maskey@Sun.COM 	if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG,
50111767SAnurag.Maskey@Sun.COM 	    OUR_OLD_DHCP_WAIT_TIME_PROP_NAME, &dhcp_wait_time) == 0) {
50211767SAnurag.Maskey@Sun.COM 		(void) nwamd_set_count_property(OUR_FMRI, OUR_PG,
50311767SAnurag.Maskey@Sun.COM 		    OUR_NCU_WAIT_TIME_PROP_NAME, dhcp_wait_time);
50411767SAnurag.Maskey@Sun.COM 		(void) nwamd_delete_scf_property(OUR_FMRI, OUR_PG,
50511767SAnurag.Maskey@Sun.COM 		    OUR_OLD_DHCP_WAIT_TIME_PROP_NAME);
50611767SAnurag.Maskey@Sun.COM 		nlog(LOG_DEBUG, "nwamd_handle_upgrade: "
50711767SAnurag.Maskey@Sun.COM 		    "converted '%s' to '%s' with value of %lld",
50811767SAnurag.Maskey@Sun.COM 		    OUR_OLD_DHCP_WAIT_TIME_PROP_NAME,
50911767SAnurag.Maskey@Sun.COM 		    OUR_NCU_WAIT_TIME_PROP_NAME, dhcp_wait_time);
5107645Sjames.d.carlson@sun.com 	}
5117645Sjames.d.carlson@sun.com 
51211767SAnurag.Maskey@Sun.COM 	/*
51311767SAnurag.Maskey@Sun.COM 	 * If the user has changed Phase 0/0.5 properties that don't exist in
51411767SAnurag.Maskey@Sun.COM 	 * Phase 1, manifest-import reports a warning; but those properties are
51511767SAnurag.Maskey@Sun.COM 	 * not removed.  nwamd/use_net_svc and nwamd/idle_time are two
51611767SAnurag.Maskey@Sun.COM 	 * properties that don't exist in Phase 1.  If they exist, remove them.
51711767SAnurag.Maskey@Sun.COM 	 */
51811767SAnurag.Maskey@Sun.COM 	if (nwamd_lookup_count_property(OUR_FMRI, OUR_PG,
51911767SAnurag.Maskey@Sun.COM 	    OUR_OLD_IDLE_TIME_PROP_NAME, &idle_time) == 0) {
52011767SAnurag.Maskey@Sun.COM 		(void) nwamd_delete_scf_property(OUR_FMRI, OUR_PG,
52111767SAnurag.Maskey@Sun.COM 		    OUR_OLD_IDLE_TIME_PROP_NAME);
5227645Sjames.d.carlson@sun.com 	}
52311767SAnurag.Maskey@Sun.COM 	if (nwamd_lookup_boolean_property(OUR_FMRI, OUR_PG,
52411767SAnurag.Maskey@Sun.COM 	    OUR_OLD_USE_NET_SVC_PROP_NAME, &use_net_svc) == 0) {
52511767SAnurag.Maskey@Sun.COM 		(void) nwamd_delete_scf_property(OUR_FMRI, OUR_PG,
52611767SAnurag.Maskey@Sun.COM 		    OUR_OLD_USE_NET_SVC_PROP_NAME);
52711767SAnurag.Maskey@Sun.COM 	}
52811767SAnurag.Maskey@Sun.COM 
52911767SAnurag.Maskey@Sun.COM 	nlog(LOG_DEBUG, "nwamd_handle_upgrade: "
53011767SAnurag.Maskey@Sun.COM 	    "creating version property, setting to 1\n");
53111767SAnurag.Maskey@Sun.COM 	(void) nwamd_set_count_property(OUR_FMRI, OUR_PG,
53211767SAnurag.Maskey@Sun.COM 	    OUR_VERSION_PROP_NAME, 1U);
53311767SAnurag.Maskey@Sun.COM 	(void) smf_refresh_instance(OUR_FMRI);
5347645Sjames.d.carlson@sun.com }
535