136589d6bSRobert Mustacchi /*
236589d6bSRobert Mustacchi  * This file and its contents are supplied under the terms of the
336589d6bSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
436589d6bSRobert Mustacchi  * You may only use this file in accordance with the terms of version
536589d6bSRobert Mustacchi  * 1.0 of the CDDL.
636589d6bSRobert Mustacchi  *
736589d6bSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
836589d6bSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
936589d6bSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
1036589d6bSRobert Mustacchi  */
1136589d6bSRobert Mustacchi 
1236589d6bSRobert Mustacchi /*
1336589d6bSRobert Mustacchi  * Copyright (c) 2015 Joyent, Inc.
14faa2068dSAndy Fiddaman  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
1536589d6bSRobert Mustacchi  */
1636589d6bSRobert Mustacchi 
1736589d6bSRobert Mustacchi #include <libdladm_impl.h>
1836589d6bSRobert Mustacchi #include <libdllink.h>
1936589d6bSRobert Mustacchi #include <libdloverlay.h>
2036589d6bSRobert Mustacchi #include <sys/dld.h>
2136589d6bSRobert Mustacchi #include <sys/overlay.h>
2236589d6bSRobert Mustacchi #include <strings.h>
2336589d6bSRobert Mustacchi #include <unistd.h>
2436589d6bSRobert Mustacchi #include <stdlib.h>
2536589d6bSRobert Mustacchi #include <errno.h>
2636589d6bSRobert Mustacchi #include <netinet/in.h>
2736589d6bSRobert Mustacchi #include <arpa/inet.h>
2836589d6bSRobert Mustacchi #include <limits.h>
29faa2068dSAndy Fiddaman #include <libscf.h>
3036589d6bSRobert Mustacchi #include <libvarpd_client.h>
3136589d6bSRobert Mustacchi 
3236589d6bSRobert Mustacchi #define	VARPD_PROPERTY_NAME	"varpd/id"
33faa2068dSAndy Fiddaman #define	VARPD_SERVICE		"network/varpd:default"
3436589d6bSRobert Mustacchi 
3536589d6bSRobert Mustacchi static const char *dladm_overlay_doorpath = "/var/run/varpd/varpd.door";
3636589d6bSRobert Mustacchi 
37faa2068dSAndy Fiddaman static boolean_t
varpd_svc_isonline(void)38faa2068dSAndy Fiddaman varpd_svc_isonline(void)
39faa2068dSAndy Fiddaman {
40faa2068dSAndy Fiddaman 	boolean_t isonline = B_FALSE;
41faa2068dSAndy Fiddaman 	char *s;
42faa2068dSAndy Fiddaman 
43faa2068dSAndy Fiddaman 	if ((s = smf_get_state(VARPD_SERVICE)) != NULL) {
44faa2068dSAndy Fiddaman 		if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0)
45faa2068dSAndy Fiddaman 			isonline = B_TRUE;
46faa2068dSAndy Fiddaman 		free(s);
47faa2068dSAndy Fiddaman 	}
48faa2068dSAndy Fiddaman 
49faa2068dSAndy Fiddaman 	return (isonline);
50faa2068dSAndy Fiddaman }
51faa2068dSAndy Fiddaman 
52faa2068dSAndy Fiddaman #define	MAX_WAIT_TIME	15
53faa2068dSAndy Fiddaman 
54faa2068dSAndy Fiddaman static dladm_status_t
varpd_enable_service(void)55faa2068dSAndy Fiddaman varpd_enable_service(void)
56faa2068dSAndy Fiddaman {
57faa2068dSAndy Fiddaman 	uint_t i;
58faa2068dSAndy Fiddaman 
59faa2068dSAndy Fiddaman 	if (varpd_svc_isonline())
60faa2068dSAndy Fiddaman 		return (DLADM_STATUS_OK);
61faa2068dSAndy Fiddaman 
62faa2068dSAndy Fiddaman 	if (smf_enable_instance(VARPD_SERVICE, 0) == -1) {
63faa2068dSAndy Fiddaman 		if (scf_error() == SCF_ERROR_PERMISSION_DENIED)
64faa2068dSAndy Fiddaman 			return (DLADM_STATUS_DENIED);
65faa2068dSAndy Fiddaman 		return (DLADM_STATUS_NOTFOUND);
66faa2068dSAndy Fiddaman 	}
67faa2068dSAndy Fiddaman 
68faa2068dSAndy Fiddaman 	/*
69faa2068dSAndy Fiddaman 	 * Wait up to MAX_WAIT_TIME seconds for the service
70faa2068dSAndy Fiddaman 	 */
71faa2068dSAndy Fiddaman 	for (i = 0; i < MAX_WAIT_TIME; i++) {
72faa2068dSAndy Fiddaman 		if (varpd_svc_isonline())
73faa2068dSAndy Fiddaman 			return (DLADM_STATUS_OK);
74faa2068dSAndy Fiddaman 		(void) sleep(1);
75faa2068dSAndy Fiddaman 	}
76faa2068dSAndy Fiddaman 	return (DLADM_STATUS_FAILED);
77faa2068dSAndy Fiddaman }
78faa2068dSAndy Fiddaman 
79faa2068dSAndy Fiddaman static int
dladm_overlay_count_cb(dladm_handle_t handle __unused,datalink_id_t linkid __unused,void * arg)8020535e13SToomas Soome dladm_overlay_count_cb(dladm_handle_t handle __unused,
8120535e13SToomas Soome     datalink_id_t linkid __unused, void *arg)
82faa2068dSAndy Fiddaman {
83faa2068dSAndy Fiddaman 	(*(uint32_t *)arg)++;
84faa2068dSAndy Fiddaman 	return (DLADM_WALK_CONTINUE);
85faa2068dSAndy Fiddaman }
86faa2068dSAndy Fiddaman 
87faa2068dSAndy Fiddaman /*
88faa2068dSAndy Fiddaman  * Disable the varpd service if there are no overlays left.
89faa2068dSAndy Fiddaman  */
90faa2068dSAndy Fiddaman static void
varpd_disable_service_when_no_overlays(dladm_handle_t handle)91faa2068dSAndy Fiddaman varpd_disable_service_when_no_overlays(dladm_handle_t handle)
92faa2068dSAndy Fiddaman {
93faa2068dSAndy Fiddaman 	uint32_t cnt = 0;
94faa2068dSAndy Fiddaman 
95faa2068dSAndy Fiddaman 	/*
96faa2068dSAndy Fiddaman 	 * Get the number of the existing overlays. If there are no overlays
97faa2068dSAndy Fiddaman 	 * left, disable the service.
98faa2068dSAndy Fiddaman 	 */
99faa2068dSAndy Fiddaman 
100faa2068dSAndy Fiddaman 	(void) dladm_walk_datalink_id(dladm_overlay_count_cb, handle,
101faa2068dSAndy Fiddaman 	    &cnt, DATALINK_CLASS_OVERLAY, DATALINK_ANY_MEDIATYPE,
102faa2068dSAndy Fiddaman 	    DLADM_OPT_ACTIVE);
103faa2068dSAndy Fiddaman 
104faa2068dSAndy Fiddaman 	if (cnt == 0)
105faa2068dSAndy Fiddaman 		(void) smf_disable_instance(VARPD_SERVICE, 0);
106faa2068dSAndy Fiddaman }
107faa2068dSAndy Fiddaman 
10836589d6bSRobert Mustacchi typedef struct dladm_overlay_propinfo {
10936589d6bSRobert Mustacchi 	boolean_t dop_isvarpd;
11036589d6bSRobert Mustacchi 	union {
11136589d6bSRobert Mustacchi 		overlay_ioc_propinfo_t *dop_overlay;
11236589d6bSRobert Mustacchi 		varpd_client_prop_handle_t *dop_varpd;
11336589d6bSRobert Mustacchi 	} dop_un;
11436589d6bSRobert Mustacchi } dladm_overlay_propinfo_t;
11536589d6bSRobert Mustacchi 
11636589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_prop_info(dladm_overlay_propinfo_handle_t phdl,const char ** namep,uint_t * typep,uint_t * protp,const void ** defp,uint32_t * sizep,const mac_propval_range_t ** possp)11736589d6bSRobert Mustacchi dladm_overlay_prop_info(dladm_overlay_propinfo_handle_t phdl,
11836589d6bSRobert Mustacchi     const char **namep, uint_t *typep, uint_t *protp, const void **defp,
11936589d6bSRobert Mustacchi     uint32_t *sizep, const mac_propval_range_t **possp)
12036589d6bSRobert Mustacchi {
12136589d6bSRobert Mustacchi 	dladm_overlay_propinfo_t *infop = (dladm_overlay_propinfo_t *)phdl;
12236589d6bSRobert Mustacchi 	overlay_ioc_propinfo_t *oinfop = infop->dop_un.dop_overlay;
12336589d6bSRobert Mustacchi 
12436589d6bSRobert Mustacchi 	if (infop->dop_isvarpd == B_FALSE) {
12536589d6bSRobert Mustacchi 		if (namep != NULL)
12636589d6bSRobert Mustacchi 			*namep = oinfop->oipi_name;
12736589d6bSRobert Mustacchi 		if (typep != NULL)
12836589d6bSRobert Mustacchi 			*typep = oinfop->oipi_type;
12936589d6bSRobert Mustacchi 		if (protp != NULL)
13036589d6bSRobert Mustacchi 			*protp = oinfop->oipi_prot;
13136589d6bSRobert Mustacchi 		if (defp != NULL)
13236589d6bSRobert Mustacchi 			*defp = oinfop->oipi_default;
13336589d6bSRobert Mustacchi 		if (sizep != NULL)
13436589d6bSRobert Mustacchi 			*sizep = oinfop->oipi_defsize;
13536589d6bSRobert Mustacchi 		if (possp != NULL) {
13636589d6bSRobert Mustacchi 			*possp = (const mac_propval_range_t *)oinfop->oipi_poss;
13736589d6bSRobert Mustacchi 		}
13836589d6bSRobert Mustacchi 
13936589d6bSRobert Mustacchi 	} else {
14036589d6bSRobert Mustacchi 		int ret;
14136589d6bSRobert Mustacchi 		ret = libvarpd_c_prop_info(infop->dop_un.dop_varpd, namep,
14236589d6bSRobert Mustacchi 		    typep, protp, defp, sizep, possp);
14336589d6bSRobert Mustacchi 		if (ret != 0)
14436589d6bSRobert Mustacchi 			return (dladm_errno2status(ret));
14536589d6bSRobert Mustacchi 
14636589d6bSRobert Mustacchi 	}
14736589d6bSRobert Mustacchi 
14836589d6bSRobert Mustacchi 	return (DLADM_STATUS_OK);
14936589d6bSRobert Mustacchi }
15036589d6bSRobert Mustacchi 
15136589d6bSRobert Mustacchi static dladm_status_t
dladm_overlay_parse_prop(overlay_prop_type_t type,void * buf,uint32_t * sizep,const char * val)15236589d6bSRobert Mustacchi dladm_overlay_parse_prop(overlay_prop_type_t type, void *buf, uint32_t *sizep,
15336589d6bSRobert Mustacchi     const char *val)
15436589d6bSRobert Mustacchi {
15536589d6bSRobert Mustacchi 	int ret;
15636589d6bSRobert Mustacchi 	int64_t ival;
15736589d6bSRobert Mustacchi 	uint64_t uval;
15836589d6bSRobert Mustacchi 	char *eptr;
15936589d6bSRobert Mustacchi 	struct in6_addr ipv6;
16036589d6bSRobert Mustacchi 	struct in_addr ip;
16136589d6bSRobert Mustacchi 
16236589d6bSRobert Mustacchi 	switch (type) {
16336589d6bSRobert Mustacchi 	case OVERLAY_PROP_T_INT:
16436589d6bSRobert Mustacchi 		errno = 0;
16536589d6bSRobert Mustacchi 		ival = strtol(val, &eptr, 10);
16636589d6bSRobert Mustacchi 		if ((ival == 0 && errno == EINVAL) ||
16736589d6bSRobert Mustacchi 		    ((ival == LONG_MAX || ival == LONG_MIN) &&
16836589d6bSRobert Mustacchi 		    errno == ERANGE))
16936589d6bSRobert Mustacchi 			return (DLADM_STATUS_BADARG);
17036589d6bSRobert Mustacchi 		bcopy(&ival, buf, sizeof (int64_t));
17136589d6bSRobert Mustacchi 		*sizep = sizeof (int64_t);
17236589d6bSRobert Mustacchi 		break;
17336589d6bSRobert Mustacchi 	case OVERLAY_PROP_T_UINT:
17436589d6bSRobert Mustacchi 		errno = 0;
17536589d6bSRobert Mustacchi 		uval = strtol(val, &eptr, 10);
17636589d6bSRobert Mustacchi 		if ((uval == 0 && errno == EINVAL) ||
17736589d6bSRobert Mustacchi 		    (uval == ULONG_MAX && errno == ERANGE))
17836589d6bSRobert Mustacchi 			return (DLADM_STATUS_BADARG);
17936589d6bSRobert Mustacchi 		bcopy(&uval, buf, sizeof (uint64_t));
18036589d6bSRobert Mustacchi 		*sizep = sizeof (uint64_t);
18136589d6bSRobert Mustacchi 		break;
18236589d6bSRobert Mustacchi 	case OVERLAY_PROP_T_STRING:
18336589d6bSRobert Mustacchi 		ret = strlcpy((char *)buf, val, OVERLAY_PROP_SIZEMAX);
18436589d6bSRobert Mustacchi 		if (ret >= OVERLAY_PROP_SIZEMAX)
18536589d6bSRobert Mustacchi 			return (DLADM_STATUS_BADARG);
18636589d6bSRobert Mustacchi 		*sizep = ret + 1;
18736589d6bSRobert Mustacchi 		break;
18836589d6bSRobert Mustacchi 	case OVERLAY_PROP_T_IP:
18936589d6bSRobert Mustacchi 		/*
19036589d6bSRobert Mustacchi 		 * Always try to parse the IP as an IPv6 address. If that fails,
19136589d6bSRobert Mustacchi 		 * try to interpret it as an IPv4 address and transform it into
19236589d6bSRobert Mustacchi 		 * an IPv6 mapped IPv4 address.
19336589d6bSRobert Mustacchi 		 */
19436589d6bSRobert Mustacchi 		if (inet_pton(AF_INET6, val, &ipv6) != 1) {
19536589d6bSRobert Mustacchi 			if (inet_pton(AF_INET, val, &ip) != 1)
19636589d6bSRobert Mustacchi 				return (DLADM_STATUS_BADARG);
19736589d6bSRobert Mustacchi 
19836589d6bSRobert Mustacchi 			IN6_INADDR_TO_V4MAPPED(&ip, &ipv6);
19936589d6bSRobert Mustacchi 		}
20036589d6bSRobert Mustacchi 		bcopy(&ipv6, buf, sizeof (struct in6_addr));
20136589d6bSRobert Mustacchi 		*sizep = sizeof (struct in6_addr);
20236589d6bSRobert Mustacchi 		break;
20336589d6bSRobert Mustacchi 	default:
20436589d6bSRobert Mustacchi 		abort();
20536589d6bSRobert Mustacchi 	}
20636589d6bSRobert Mustacchi 
20736589d6bSRobert Mustacchi 	return (DLADM_STATUS_OK);
20836589d6bSRobert Mustacchi }
20936589d6bSRobert Mustacchi 
21036589d6bSRobert Mustacchi static dladm_status_t
i_dladm_overlay_setprop_db(dladm_handle_t handle,datalink_id_t linkid,const char * name,char * const * valp,uint_t cnt)211faa2068dSAndy Fiddaman i_dladm_overlay_setprop_db(dladm_handle_t handle, datalink_id_t linkid,
212faa2068dSAndy Fiddaman     const char *name, char *const *valp, uint_t cnt)
213faa2068dSAndy Fiddaman {
214faa2068dSAndy Fiddaman 	dladm_conf_t	conf;
215faa2068dSAndy Fiddaman 	dladm_status_t	status;
216faa2068dSAndy Fiddaman 
217faa2068dSAndy Fiddaman 	if (linkid == DATALINK_INVALID_LINKID ||
218faa2068dSAndy Fiddaman 	    name == NULL || valp == NULL || cnt != 1) {
219faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
220faa2068dSAndy Fiddaman 	}
221faa2068dSAndy Fiddaman 
222faa2068dSAndy Fiddaman 	status = dladm_open_conf(handle, linkid, &conf);
223faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
224faa2068dSAndy Fiddaman 		return (status);
225faa2068dSAndy Fiddaman 
226faa2068dSAndy Fiddaman 	status = dladm_set_conf_field(handle, conf, name, DLADM_TYPE_STR,
227faa2068dSAndy Fiddaman 	    valp[0]);
228faa2068dSAndy Fiddaman 	if (status == DLADM_STATUS_OK)
229faa2068dSAndy Fiddaman 		status = dladm_write_conf(handle, conf);
230faa2068dSAndy Fiddaman 
231faa2068dSAndy Fiddaman 	dladm_destroy_conf(handle, conf);
232faa2068dSAndy Fiddaman 	return (status);
233faa2068dSAndy Fiddaman }
234faa2068dSAndy Fiddaman 
235faa2068dSAndy Fiddaman static dladm_status_t
dladm_overlay_varpd_setprop(dladm_handle_t handle __unused,varpd_client_handle_t * chdl,uint64_t inst,datalink_id_t linkid __unused,const char * name,char * const * valp,uint_t cnt __unused)23620535e13SToomas Soome dladm_overlay_varpd_setprop(dladm_handle_t handle __unused,
23720535e13SToomas Soome     varpd_client_handle_t *chdl, uint64_t inst, datalink_id_t linkid __unused,
23820535e13SToomas Soome     const char *name, char *const *valp, uint_t cnt __unused)
23936589d6bSRobert Mustacchi {
24036589d6bSRobert Mustacchi 	int ret;
24136589d6bSRobert Mustacchi 	uint32_t size;
24236589d6bSRobert Mustacchi 	uint8_t buf[LIBVARPD_PROP_SIZEMAX];
24336589d6bSRobert Mustacchi 	varpd_client_prop_handle_t *phdl;
24436589d6bSRobert Mustacchi 	uint_t type;
24536589d6bSRobert Mustacchi 	dladm_status_t status;
24636589d6bSRobert Mustacchi 
24736589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_prop_handle_alloc(chdl, inst, &phdl)) != 0)
24836589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
24936589d6bSRobert Mustacchi 
25036589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_prop_info_fill_by_name(phdl, name)) != 0) {
25136589d6bSRobert Mustacchi 		libvarpd_c_prop_handle_free(phdl);
25236589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
25336589d6bSRobert Mustacchi 	}
25436589d6bSRobert Mustacchi 
25536589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_prop_info(phdl, NULL, &type, NULL, NULL, NULL,
25636589d6bSRobert Mustacchi 	    NULL)) != 0) {
25736589d6bSRobert Mustacchi 		libvarpd_c_prop_handle_free(phdl);
25836589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
25936589d6bSRobert Mustacchi 	}
26036589d6bSRobert Mustacchi 
26136589d6bSRobert Mustacchi 	if ((status = dladm_overlay_parse_prop(type, buf, &size, valp[0])) !=
26236589d6bSRobert Mustacchi 	    DLADM_STATUS_OK) {
26336589d6bSRobert Mustacchi 		libvarpd_c_prop_handle_free(phdl);
26436589d6bSRobert Mustacchi 		return (status);
26536589d6bSRobert Mustacchi 	}
26636589d6bSRobert Mustacchi 
267faa2068dSAndy Fiddaman 	status = DLADM_STATUS_OK;
26836589d6bSRobert Mustacchi 	ret = libvarpd_c_prop_set(phdl, buf, size);
26936589d6bSRobert Mustacchi 	libvarpd_c_prop_handle_free(phdl);
270faa2068dSAndy Fiddaman 	if (ret != 0)
271faa2068dSAndy Fiddaman 		status = dladm_errno2status(ret);
27236589d6bSRobert Mustacchi 
273faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
274faa2068dSAndy Fiddaman 		return (status);
275faa2068dSAndy Fiddaman 
276faa2068dSAndy Fiddaman 	return (status);
27736589d6bSRobert Mustacchi }
27836589d6bSRobert Mustacchi 
279faa2068dSAndy Fiddaman static dladm_status_t
dladm_overlay_setprop(dladm_handle_t handle,datalink_id_t linkid,const char * name,char * const * valp,uint_t cnt)28036589d6bSRobert Mustacchi dladm_overlay_setprop(dladm_handle_t handle, datalink_id_t linkid,
28136589d6bSRobert Mustacchi     const char *name, char *const *valp, uint_t cnt)
28236589d6bSRobert Mustacchi {
28336589d6bSRobert Mustacchi 	int			ret;
28436589d6bSRobert Mustacchi 	dladm_status_t		status;
28536589d6bSRobert Mustacchi 	overlay_ioc_propinfo_t	info;
28636589d6bSRobert Mustacchi 	overlay_ioc_prop_t	prop;
28736589d6bSRobert Mustacchi 
28836589d6bSRobert Mustacchi 	if (linkid == DATALINK_INVALID_LINKID ||
28936589d6bSRobert Mustacchi 	    name == NULL || valp == NULL || cnt != 1)
29036589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
29136589d6bSRobert Mustacchi 
29236589d6bSRobert Mustacchi 	bzero(&info, sizeof (overlay_ioc_propinfo_t));
29336589d6bSRobert Mustacchi 	info.oipi_linkid = linkid;
29436589d6bSRobert Mustacchi 	info.oipi_id = -1;
29536589d6bSRobert Mustacchi 	if (strlcpy(info.oipi_name, name, OVERLAY_PROP_NAMELEN) >=
29636589d6bSRobert Mustacchi 	    OVERLAY_PROP_NAMELEN)
29736589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
29836589d6bSRobert Mustacchi 
29936589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
30036589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_PROPINFO, &info);
30136589d6bSRobert Mustacchi 	if (ret != 0)
30236589d6bSRobert Mustacchi 		status = dladm_errno2status(errno);
30336589d6bSRobert Mustacchi 
30436589d6bSRobert Mustacchi 	if (status != DLADM_STATUS_OK)
30536589d6bSRobert Mustacchi 		return (status);
30636589d6bSRobert Mustacchi 
30736589d6bSRobert Mustacchi 	prop.oip_linkid = linkid;
30836589d6bSRobert Mustacchi 	prop.oip_id = info.oipi_id;
30936589d6bSRobert Mustacchi 	prop.oip_name[0] = '\0';
310faa2068dSAndy Fiddaman 	if ((status = dladm_overlay_parse_prop(info.oipi_type, prop.oip_value,
31136589d6bSRobert Mustacchi 	    &prop.oip_size, valp[0])) != DLADM_STATUS_OK)
312faa2068dSAndy Fiddaman 		return (status);
31336589d6bSRobert Mustacchi 
31436589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
31536589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_SETPROP, &prop);
31636589d6bSRobert Mustacchi 	if (ret != 0)
31736589d6bSRobert Mustacchi 		status = dladm_errno2status(errno);
31836589d6bSRobert Mustacchi 
319faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
320faa2068dSAndy Fiddaman 		return (status);
321faa2068dSAndy Fiddaman 
322faa2068dSAndy Fiddaman 	return (status);
32336589d6bSRobert Mustacchi }
32436589d6bSRobert Mustacchi 
32536589d6bSRobert Mustacchi /*
32636589d6bSRobert Mustacchi  * Tell the user about any unset required properties.
32736589d6bSRobert Mustacchi  */
32836589d6bSRobert Mustacchi static int
dladm_overlay_activate_cb(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_propinfo_handle_t phdl,void * arg)32936589d6bSRobert Mustacchi dladm_overlay_activate_cb(dladm_handle_t handle, datalink_id_t linkid,
33036589d6bSRobert Mustacchi     dladm_overlay_propinfo_handle_t phdl, void *arg)
33136589d6bSRobert Mustacchi {
33236589d6bSRobert Mustacchi 	dladm_status_t status;
33336589d6bSRobert Mustacchi 	uint8_t buf[DLADM_OVERLAY_PROP_SIZEMAX];
33436589d6bSRobert Mustacchi 	uint_t prot;
33536589d6bSRobert Mustacchi 	size_t size = sizeof (buf);
33636589d6bSRobert Mustacchi 	const char *name;
33736589d6bSRobert Mustacchi 	dladm_errlist_t *errs = arg;
33836589d6bSRobert Mustacchi 
33936589d6bSRobert Mustacchi 	if ((status = dladm_overlay_prop_info(phdl, &name, NULL, &prot, NULL,
34036589d6bSRobert Mustacchi 	    NULL, NULL)) != DLADM_STATUS_OK)
34136589d6bSRobert Mustacchi 		return (status);
34236589d6bSRobert Mustacchi 
34336589d6bSRobert Mustacchi 	if ((prot & OVERLAY_PROP_PERM_REQ) == 0)
34436589d6bSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
34536589d6bSRobert Mustacchi 
34636589d6bSRobert Mustacchi 	if (dladm_overlay_get_prop(handle, linkid, phdl, buf, &size) !=
34736589d6bSRobert Mustacchi 	    DLADM_STATUS_OK)
34836589d6bSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
34936589d6bSRobert Mustacchi 
35036589d6bSRobert Mustacchi 	if (size == 0)
35136589d6bSRobert Mustacchi 		(void) dladm_errlist_append(errs, "unset required property: %s",
35236589d6bSRobert Mustacchi 		    name);
35336589d6bSRobert Mustacchi 
35436589d6bSRobert Mustacchi 	return (DLADM_WALK_CONTINUE);
35536589d6bSRobert Mustacchi }
35636589d6bSRobert Mustacchi 
35736589d6bSRobert Mustacchi /*
35836589d6bSRobert Mustacchi  * We need to clean up the world here. The problem is that we may or may not
35936589d6bSRobert Mustacchi  * actually have everything created. While in the normal case, we'd always have
36036589d6bSRobert Mustacchi  * an overlay device, assigned datalink id, and a varpd instance, we might not
36136589d6bSRobert Mustacchi  * have any of those, except for the datalink instance. Therefore, as long as
36236589d6bSRobert Mustacchi  * the id refers to a valid overlay, we should try to clean up as much of the
36336589d6bSRobert Mustacchi  * state as possible and most importantly, we need to make sure we delete the
36436589d6bSRobert Mustacchi  * datalink id. If we fail to do that, then that name will become lost to time.
36536589d6bSRobert Mustacchi  */
36636589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_delete(dladm_handle_t handle,datalink_id_t linkid,uint32_t flags)367faa2068dSAndy Fiddaman dladm_overlay_delete(dladm_handle_t handle, datalink_id_t linkid,
368faa2068dSAndy Fiddaman     uint32_t flags)
36936589d6bSRobert Mustacchi {
37036589d6bSRobert Mustacchi 	datalink_class_t class;
37136589d6bSRobert Mustacchi 	overlay_ioc_delete_t oid;
37236589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
37336589d6bSRobert Mustacchi 	int ret;
37436589d6bSRobert Mustacchi 	uint64_t varpdid;
37536589d6bSRobert Mustacchi 
376faa2068dSAndy Fiddaman 	if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
377faa2068dSAndy Fiddaman 	    NULL, 0) != DLADM_STATUS_OK) {
37836589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
379faa2068dSAndy Fiddaman 	}
38036589d6bSRobert Mustacchi 
38136589d6bSRobert Mustacchi 	if (class != DATALINK_CLASS_OVERLAY)
38236589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
38336589d6bSRobert Mustacchi 
38436589d6bSRobert Mustacchi 	oid.oid_linkid = linkid;
38536589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_DELETE, &oid);
38636589d6bSRobert Mustacchi 	if (ret != 0 && errno != ENOENT) {
38736589d6bSRobert Mustacchi 		return (dladm_errno2status(errno));
38836589d6bSRobert Mustacchi 	}
38936589d6bSRobert Mustacchi 
39036589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0) {
39136589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
39236589d6bSRobert Mustacchi 	}
39336589d6bSRobert Mustacchi 
39436589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
39536589d6bSRobert Mustacchi 		if (ret == ENOENT) {
39636589d6bSRobert Mustacchi 			goto finish;
39736589d6bSRobert Mustacchi 		}
39836589d6bSRobert Mustacchi 		(void) libvarpd_c_destroy(chdl);
39936589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
40036589d6bSRobert Mustacchi 	}
40136589d6bSRobert Mustacchi 
40236589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_destroy(chdl, varpdid);
40336589d6bSRobert Mustacchi finish:
40436589d6bSRobert Mustacchi 	(void) libvarpd_c_destroy(chdl);
405faa2068dSAndy Fiddaman 	if ((flags & DLADM_OPT_PERSIST) != 0) {
406faa2068dSAndy Fiddaman 		(void) dladm_remove_conf(handle, linkid);
407faa2068dSAndy Fiddaman 		(void) dladm_destroy_datalink_id(handle, linkid, flags);
408faa2068dSAndy Fiddaman 	}
409faa2068dSAndy Fiddaman 
410faa2068dSAndy Fiddaman 	(void) varpd_disable_service_when_no_overlays(handle);
41136589d6bSRobert Mustacchi 
41236589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
41336589d6bSRobert Mustacchi }
41436589d6bSRobert Mustacchi 
41536589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_get_prop(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_propinfo_handle_t infohdl,void * buf,size_t * sizep)41636589d6bSRobert Mustacchi dladm_overlay_get_prop(dladm_handle_t handle, datalink_id_t linkid,
41736589d6bSRobert Mustacchi     dladm_overlay_propinfo_handle_t infohdl, void *buf, size_t *sizep)
41836589d6bSRobert Mustacchi {
41936589d6bSRobert Mustacchi 	int ret;
42036589d6bSRobert Mustacchi 	overlay_ioc_prop_t oip;
42136589d6bSRobert Mustacchi 	dladm_overlay_propinfo_t *infop = (dladm_overlay_propinfo_t *)infohdl;
42236589d6bSRobert Mustacchi 
42336589d6bSRobert Mustacchi 	/*
42436589d6bSRobert Mustacchi 	 * It'd be nice if we had a better or more specific error for this. If
42536589d6bSRobert Mustacchi 	 * this kind of error becomes common place, let's get a better dladm
42636589d6bSRobert Mustacchi 	 * error.
42736589d6bSRobert Mustacchi 	 */
42836589d6bSRobert Mustacchi 	if (*sizep < DLADM_OVERLAY_PROP_SIZEMAX)
42936589d6bSRobert Mustacchi 		return (dladm_errno2status(ERANGE));
43036589d6bSRobert Mustacchi 
43136589d6bSRobert Mustacchi 	if (infop->dop_isvarpd == B_FALSE) {
43236589d6bSRobert Mustacchi 		bzero(&oip, sizeof (overlay_ioc_prop_t));
43336589d6bSRobert Mustacchi 		oip.oip_linkid = linkid;
43436589d6bSRobert Mustacchi 		oip.oip_id = infop->dop_un.dop_overlay->oipi_id;
43536589d6bSRobert Mustacchi 		ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_GETPROP, &oip);
43636589d6bSRobert Mustacchi 		if (ret != 0)
43736589d6bSRobert Mustacchi 			return (dladm_errno2status(errno));
43836589d6bSRobert Mustacchi 		bcopy(oip.oip_value, buf, DLADM_OVERLAY_PROP_SIZEMAX);
43936589d6bSRobert Mustacchi 		*sizep = oip.oip_size;
44036589d6bSRobert Mustacchi 	} else {
44136589d6bSRobert Mustacchi 		uint32_t size = *sizep;
44236589d6bSRobert Mustacchi 
44336589d6bSRobert Mustacchi 		ret = libvarpd_c_prop_get(infop->dop_un.dop_varpd, buf, &size);
44436589d6bSRobert Mustacchi 		if (ret != 0)
44536589d6bSRobert Mustacchi 			return (dladm_errno2status(errno));
44636589d6bSRobert Mustacchi 		*sizep = size;
44736589d6bSRobert Mustacchi 	}
44836589d6bSRobert Mustacchi 
44936589d6bSRobert Mustacchi 	return (DLADM_STATUS_OK);
45036589d6bSRobert Mustacchi }
45136589d6bSRobert Mustacchi 
45236589d6bSRobert Mustacchi static dladm_status_t
dladm_overlay_walk_varpd_prop(dladm_handle_t handle,datalink_id_t linkid,uint64_t varpdid,dladm_overlay_prop_f func,void * arg)45336589d6bSRobert Mustacchi dladm_overlay_walk_varpd_prop(dladm_handle_t handle, datalink_id_t linkid,
45436589d6bSRobert Mustacchi     uint64_t varpdid, dladm_overlay_prop_f func, void *arg)
45536589d6bSRobert Mustacchi {
456*4202e8bfSToomas Soome 	int ret;
45736589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
45836589d6bSRobert Mustacchi 	varpd_client_prop_handle_t *phdl;
459*4202e8bfSToomas Soome 	uint_t i, nprops;
46036589d6bSRobert Mustacchi 	dladm_status_t status;
46136589d6bSRobert Mustacchi 
46236589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
46336589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
46436589d6bSRobert Mustacchi 
46536589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_prop_handle_alloc(chdl, varpdid, &phdl)) != 0) {
46636589d6bSRobert Mustacchi 		(void) libvarpd_c_destroy(chdl);
46736589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
46836589d6bSRobert Mustacchi 	}
46936589d6bSRobert Mustacchi 
47036589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_prop_nprops(chdl, varpdid, &nprops)) != 0) {
47136589d6bSRobert Mustacchi 		libvarpd_c_prop_handle_free(phdl);
47236589d6bSRobert Mustacchi 		(void) libvarpd_c_destroy(chdl);
47336589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
47436589d6bSRobert Mustacchi 	}
47536589d6bSRobert Mustacchi 
47636589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
47736589d6bSRobert Mustacchi 	for (i = 0; i < nprops; i++) {
47836589d6bSRobert Mustacchi 		dladm_overlay_propinfo_t dop;
47936589d6bSRobert Mustacchi 
48036589d6bSRobert Mustacchi 		bzero(&dop, sizeof (dop));
48136589d6bSRobert Mustacchi 		dop.dop_isvarpd = B_TRUE;
48236589d6bSRobert Mustacchi 		dop.dop_un.dop_varpd = phdl;
48336589d6bSRobert Mustacchi 
48436589d6bSRobert Mustacchi 		if ((ret = libvarpd_c_prop_info_fill(phdl, i)) != 0) {
48536589d6bSRobert Mustacchi 			status = dladm_errno2status(ret);
48636589d6bSRobert Mustacchi 			break;
48736589d6bSRobert Mustacchi 		}
48836589d6bSRobert Mustacchi 
48936589d6bSRobert Mustacchi 		ret = func(handle, linkid,
49036589d6bSRobert Mustacchi 		    (dladm_overlay_propinfo_handle_t)&dop, arg);
49136589d6bSRobert Mustacchi 		if (ret == DLADM_WALK_TERMINATE)
49236589d6bSRobert Mustacchi 			break;
49336589d6bSRobert Mustacchi 	}
49436589d6bSRobert Mustacchi 
49536589d6bSRobert Mustacchi 	libvarpd_c_prop_handle_free(phdl);
49636589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
49736589d6bSRobert Mustacchi 
49836589d6bSRobert Mustacchi 	return (status);
49936589d6bSRobert Mustacchi }
50036589d6bSRobert Mustacchi 
50136589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_walk_prop(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_prop_f func,void * arg,dladm_errlist_t * errs)50236589d6bSRobert Mustacchi dladm_overlay_walk_prop(dladm_handle_t handle, datalink_id_t linkid,
50336589d6bSRobert Mustacchi     dladm_overlay_prop_f func, void *arg, dladm_errlist_t *errs)
50436589d6bSRobert Mustacchi {
50536589d6bSRobert Mustacchi 	int i, ret;
50629ed1476SIsaac Davis 	char buf[MAXLINKNAMELEN];
50729ed1476SIsaac Davis 	char errmsg[DLADM_STRSIZE];
50836589d6bSRobert Mustacchi 	datalink_class_t class;
50929ed1476SIsaac Davis 	dladm_status_t info_status;
51036589d6bSRobert Mustacchi 	overlay_ioc_nprops_t oin;
51136589d6bSRobert Mustacchi 	overlay_ioc_propinfo_t oipi;
51236589d6bSRobert Mustacchi 	dladm_overlay_propinfo_t dop;
51336589d6bSRobert Mustacchi 	uint64_t varpdid = UINT64_MAX;
51436589d6bSRobert Mustacchi 
51529ed1476SIsaac Davis 	if ((info_status = dladm_datalink_id2info(handle, linkid, NULL, &class,
51629ed1476SIsaac Davis 	    NULL, buf, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
51729ed1476SIsaac Davis 		(void) dladm_errlist_append(errs, "failed to get info for "
51829ed1476SIsaac Davis 		    "datalink id %u: %s",
51929ed1476SIsaac Davis 		    linkid, dladm_status2str(info_status, errmsg));
52036589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
52129ed1476SIsaac Davis 	}
52236589d6bSRobert Mustacchi 
52329ed1476SIsaac Davis 	if (class != DATALINK_CLASS_OVERLAY) {
52429ed1476SIsaac Davis 		(void) dladm_errlist_append(errs, "%s is not an overlay", buf);
52536589d6bSRobert Mustacchi 		return (DLADM_STATUS_BADARG);
52629ed1476SIsaac Davis 	}
52736589d6bSRobert Mustacchi 
52836589d6bSRobert Mustacchi 	bzero(&oin, sizeof (overlay_ioc_nprops_t));
52936589d6bSRobert Mustacchi 	oin.oipn_linkid = linkid;
53036589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_NPROPS, &oin);
53129ed1476SIsaac Davis 	if (ret != 0) {
53229ed1476SIsaac Davis 		(void) dladm_errlist_append(errs, "failed to get "
53329ed1476SIsaac Davis 		    "overlay properties for overlay %s: %s",
53429ed1476SIsaac Davis 		    buf, strerror(errno));
53536589d6bSRobert Mustacchi 		return (dladm_errno2status(errno));
53629ed1476SIsaac Davis 	}
53736589d6bSRobert Mustacchi 
53836589d6bSRobert Mustacchi 	for (i = 0; i < oin.oipn_nprops; i++) {
53936589d6bSRobert Mustacchi 		bzero(&dop, sizeof (dladm_overlay_propinfo_t));
54036589d6bSRobert Mustacchi 		bzero(&oipi, sizeof (overlay_ioc_propinfo_t));
54136589d6bSRobert Mustacchi 		oipi.oipi_linkid = linkid;
54236589d6bSRobert Mustacchi 		oipi.oipi_id = i;
54336589d6bSRobert Mustacchi 		ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_PROPINFO, &oipi);
54436589d6bSRobert Mustacchi 		if (ret != 0) {
54536589d6bSRobert Mustacchi 			(void) dladm_errlist_append(errs, "failed to get "
54629ed1476SIsaac Davis 			    "propinfo for overlay %s, property %d: %s",
54729ed1476SIsaac Davis 			    buf, i, strerror(errno));
54836589d6bSRobert Mustacchi 			return (dladm_errno2status(errno));
54936589d6bSRobert Mustacchi 		}
55036589d6bSRobert Mustacchi 
55136589d6bSRobert Mustacchi 		dop.dop_isvarpd = B_FALSE;
55236589d6bSRobert Mustacchi 		dop.dop_un.dop_overlay = &oipi;
55336589d6bSRobert Mustacchi 		ret = func(handle, linkid,
55436589d6bSRobert Mustacchi 		    (dladm_overlay_propinfo_handle_t)&dop, arg);
55536589d6bSRobert Mustacchi 		if (ret == DLADM_WALK_TERMINATE)
55636589d6bSRobert Mustacchi 			break;
55736589d6bSRobert Mustacchi 
55836589d6bSRobert Mustacchi 		if (strcmp(oipi.oipi_name, VARPD_PROPERTY_NAME) == 0) {
55936589d6bSRobert Mustacchi 			uint8_t buf[DLADM_OVERLAY_PROP_SIZEMAX];
56036589d6bSRobert Mustacchi 			size_t bufsize = sizeof (buf);
56136589d6bSRobert Mustacchi 			uint64_t *vp;
56236589d6bSRobert Mustacchi 
56336589d6bSRobert Mustacchi 			if (dladm_overlay_get_prop(handle, linkid,
56436589d6bSRobert Mustacchi 			    (dladm_overlay_propinfo_handle_t)&dop, buf,
56536589d6bSRobert Mustacchi 			    &bufsize) != DLADM_STATUS_OK)
56636589d6bSRobert Mustacchi 				continue;
56736589d6bSRobert Mustacchi 
56836589d6bSRobert Mustacchi 			vp = (uint64_t *)buf;
56936589d6bSRobert Mustacchi 			varpdid = *vp;
57036589d6bSRobert Mustacchi 		}
57136589d6bSRobert Mustacchi 	}
57236589d6bSRobert Mustacchi 
57336589d6bSRobert Mustacchi 	/* Should this really be possible? */
57436589d6bSRobert Mustacchi 	if (varpdid == UINT64_MAX)
57536589d6bSRobert Mustacchi 		return (DLADM_STATUS_OK);
57636589d6bSRobert Mustacchi 
57729ed1476SIsaac Davis 	ret = dladm_overlay_walk_varpd_prop(handle, linkid, varpdid, func,
57829ed1476SIsaac Davis 	    arg);
57929ed1476SIsaac Davis 	if (ret != DLADM_STATUS_OK) {
58029ed1476SIsaac Davis 		(void) dladm_errlist_append(errs,
58129ed1476SIsaac Davis 		    "failed to get varpd props for "
58229ed1476SIsaac Davis 		    "overlay %s, varpd id %llu: %s",
58329ed1476SIsaac Davis 		    buf, varpdid, dladm_status2str(info_status, errmsg));
58429ed1476SIsaac Davis 	}
58529ed1476SIsaac Davis 	return (ret);
58636589d6bSRobert Mustacchi }
58736589d6bSRobert Mustacchi 
588faa2068dSAndy Fiddaman static dladm_status_t
dladm_overlay_persist_config(dladm_handle_t handle,dladm_overlay_attr_t * attr)589faa2068dSAndy Fiddaman dladm_overlay_persist_config(dladm_handle_t handle, dladm_overlay_attr_t *attr)
59036589d6bSRobert Mustacchi {
591faa2068dSAndy Fiddaman 	dladm_conf_t conf;
59236589d6bSRobert Mustacchi 	dladm_status_t status;
59336589d6bSRobert Mustacchi 
594faa2068dSAndy Fiddaman 	if ((status = dladm_create_conf(handle, attr->oa_name, attr->oa_linkid,
595faa2068dSAndy Fiddaman 	    DATALINK_CLASS_OVERLAY, DL_ETHER, &conf)) != DLADM_STATUS_OK) {
59636589d6bSRobert Mustacchi 		return (status);
597faa2068dSAndy Fiddaman 	}
598faa2068dSAndy Fiddaman 
599faa2068dSAndy Fiddaman 	status = dladm_set_conf_field(handle, conf, FVNETID,
600faa2068dSAndy Fiddaman 	    DLADM_TYPE_UINT64, &attr->oa_vid);
601faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
602faa2068dSAndy Fiddaman 		goto done;
603faa2068dSAndy Fiddaman 
604faa2068dSAndy Fiddaman 	status = dladm_set_conf_field(handle, conf, FENCAP,
605faa2068dSAndy Fiddaman 	    DLADM_TYPE_STR, attr->oa_encap);
606faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
607faa2068dSAndy Fiddaman 		goto done;
608faa2068dSAndy Fiddaman 
609faa2068dSAndy Fiddaman 	status = dladm_set_conf_field(handle, conf, FSEARCH,
610faa2068dSAndy Fiddaman 	    DLADM_TYPE_STR, attr->oa_search);
611faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
612faa2068dSAndy Fiddaman 		goto done;
613faa2068dSAndy Fiddaman 
614faa2068dSAndy Fiddaman 	status = dladm_write_conf(handle, conf);
615faa2068dSAndy Fiddaman 
616faa2068dSAndy Fiddaman done:
617faa2068dSAndy Fiddaman 	dladm_destroy_conf(handle, conf);
618faa2068dSAndy Fiddaman 	return (status);
619faa2068dSAndy Fiddaman }
620faa2068dSAndy Fiddaman 
621faa2068dSAndy Fiddaman static dladm_status_t
i_dladm_overlay_create_sys(dladm_handle_t handle,dladm_overlay_attr_t * attr)622faa2068dSAndy Fiddaman i_dladm_overlay_create_sys(dladm_handle_t handle, dladm_overlay_attr_t *attr)
623faa2068dSAndy Fiddaman {
624faa2068dSAndy Fiddaman 	overlay_ioc_create_t oic;
625faa2068dSAndy Fiddaman 	dladm_status_t status;
626faa2068dSAndy Fiddaman 	int ret;
62736589d6bSRobert Mustacchi 
62836589d6bSRobert Mustacchi 	bzero(&oic, sizeof (oic));
629faa2068dSAndy Fiddaman 	oic.oic_linkid = attr->oa_linkid;
630faa2068dSAndy Fiddaman 	oic.oic_vnetid = attr->oa_vid;
631faa2068dSAndy Fiddaman 	(void) strlcpy(oic.oic_encap, attr->oa_encap, MAXLINKNAMELEN);
63236589d6bSRobert Mustacchi 
63336589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
63436589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_CREATE, &oic);
63536589d6bSRobert Mustacchi 	if (ret != 0) {
63636589d6bSRobert Mustacchi 		/*
63736589d6bSRobert Mustacchi 		 * It'd be nice if we had private errors so we could better
63836589d6bSRobert Mustacchi 		 * distinguish between different classes of errors.
63936589d6bSRobert Mustacchi 		 */
64036589d6bSRobert Mustacchi 		status = dladm_errno2status(errno);
64136589d6bSRobert Mustacchi 	}
64236589d6bSRobert Mustacchi 
643faa2068dSAndy Fiddaman 	return (status);
644faa2068dSAndy Fiddaman }
645faa2068dSAndy Fiddaman 
646faa2068dSAndy Fiddaman static dladm_status_t
i_dladm_overlay_commit_sys(dladm_handle_t handle,dladm_overlay_attr_t * attr,dladm_arg_list_t * props,dladm_errlist_t * errs)647faa2068dSAndy Fiddaman i_dladm_overlay_commit_sys(dladm_handle_t handle, dladm_overlay_attr_t *attr,
648faa2068dSAndy Fiddaman     dladm_arg_list_t *props, dladm_errlist_t *errs)
649faa2068dSAndy Fiddaman {
650faa2068dSAndy Fiddaman 	overlay_ioc_activate_t oia;
651faa2068dSAndy Fiddaman 	varpd_client_handle_t *vch;
652faa2068dSAndy Fiddaman 	dladm_status_t status;
653faa2068dSAndy Fiddaman 	size_t slen;
654faa2068dSAndy Fiddaman 	uint64_t id;
655faa2068dSAndy Fiddaman 	int ret;
656faa2068dSAndy Fiddaman 	uint_t i;
65736589d6bSRobert Mustacchi 
658faa2068dSAndy Fiddaman 	slen = strlen(attr->oa_search);
65936589d6bSRobert Mustacchi 	for (i = 0; props != NULL && i < props->al_count; i++) {
66036589d6bSRobert Mustacchi 		dladm_arg_info_t	*aip = &props->al_info[i];
66136589d6bSRobert Mustacchi 
66236589d6bSRobert Mustacchi 		/*
66336589d6bSRobert Mustacchi 		 * If it's a property for the search plugin, eg. it has the
66436589d6bSRobert Mustacchi 		 * prefix '<search>/', then we don't set the property on the
66536589d6bSRobert Mustacchi 		 * overlay device and instead set it on the varpd instance.
66636589d6bSRobert Mustacchi 		 */
667faa2068dSAndy Fiddaman 		if (strncmp(aip->ai_name, attr->oa_search, slen) == 0 &&
66836589d6bSRobert Mustacchi 		    aip->ai_name[slen] == '/')
66936589d6bSRobert Mustacchi 			continue;
670faa2068dSAndy Fiddaman 		status = dladm_overlay_setprop(handle, attr->oa_linkid,
671faa2068dSAndy Fiddaman 		    aip->ai_name, aip->ai_val, aip->ai_count);
67236589d6bSRobert Mustacchi 		if (status != DLADM_STATUS_OK) {
67336589d6bSRobert Mustacchi 			(void) dladm_errlist_append(errs,
674faa2068dSAndy Fiddaman 			    "failed to set property %s", aip->ai_name);
67536589d6bSRobert Mustacchi 			return (status);
67636589d6bSRobert Mustacchi 		}
677faa2068dSAndy Fiddaman 
678faa2068dSAndy Fiddaman 		if (attr->oa_flags & DLADM_OPT_PERSIST) {
679faa2068dSAndy Fiddaman 			status = i_dladm_overlay_setprop_db(handle,
680faa2068dSAndy Fiddaman 			    attr->oa_linkid, aip->ai_name, aip->ai_val,
681faa2068dSAndy Fiddaman 			    aip->ai_count);
682faa2068dSAndy Fiddaman 			if (status != DLADM_STATUS_OK) {
683faa2068dSAndy Fiddaman 				(void) dladm_errlist_append(errs,
684faa2068dSAndy Fiddaman 				    "failed to persistently set property %s",
685faa2068dSAndy Fiddaman 				    aip->ai_name);
686faa2068dSAndy Fiddaman 				return (status);
687faa2068dSAndy Fiddaman 			}
688faa2068dSAndy Fiddaman 		}
68936589d6bSRobert Mustacchi 	}
69036589d6bSRobert Mustacchi 
69136589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&vch, dladm_overlay_doorpath)) != 0) {
69236589d6bSRobert Mustacchi 		(void) dladm_errlist_append(errs,
69336589d6bSRobert Mustacchi 		    "failed to create libvarpd handle: %s", strerror(ret));
69436589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
69536589d6bSRobert Mustacchi 	}
69636589d6bSRobert Mustacchi 
697faa2068dSAndy Fiddaman 	if ((ret = libvarpd_c_instance_create(vch, attr->oa_linkid,
698faa2068dSAndy Fiddaman 	    attr->oa_search, &id)) != 0) {
69936589d6bSRobert Mustacchi 		(void) dladm_errlist_append(errs,
70036589d6bSRobert Mustacchi 		    "failed to create varpd instance: %s", strerror(ret));
70136589d6bSRobert Mustacchi 		libvarpd_c_destroy(vch);
70236589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
70336589d6bSRobert Mustacchi 	}
70436589d6bSRobert Mustacchi 
70536589d6bSRobert Mustacchi 	for (i = 0; props != NULL && i < props->al_count; i++) {
70636589d6bSRobert Mustacchi 		dladm_arg_info_t	*aip = &props->al_info[i];
70736589d6bSRobert Mustacchi 
70836589d6bSRobert Mustacchi 		/*
70936589d6bSRobert Mustacchi 		 * Skip arguments we've processed already.
71036589d6bSRobert Mustacchi 		 */
711faa2068dSAndy Fiddaman 		if (strncmp(aip->ai_name, attr->oa_search, slen) != 0 ||
712faa2068dSAndy Fiddaman 		    aip->ai_name[slen] != '/')
71336589d6bSRobert Mustacchi 			continue;
71436589d6bSRobert Mustacchi 
715faa2068dSAndy Fiddaman 		ret = dladm_overlay_varpd_setprop(handle, vch, id,
716faa2068dSAndy Fiddaman 		    attr->oa_linkid, aip->ai_name, aip->ai_val, aip->ai_count);
71736589d6bSRobert Mustacchi 		if (ret != 0) {
71836589d6bSRobert Mustacchi 			(void) dladm_errlist_append(errs,
719faa2068dSAndy Fiddaman 			    "failed to set varpd prop: %s\n", aip->ai_name);
72036589d6bSRobert Mustacchi 			(void) libvarpd_c_instance_destroy(vch, id);
72136589d6bSRobert Mustacchi 			libvarpd_c_destroy(vch);
72236589d6bSRobert Mustacchi 			return (dladm_errno2status(ret));
72336589d6bSRobert Mustacchi 		}
724faa2068dSAndy Fiddaman 
725faa2068dSAndy Fiddaman 		if (attr->oa_flags & DLADM_OPT_PERSIST) {
726faa2068dSAndy Fiddaman 			status = i_dladm_overlay_setprop_db(handle,
727faa2068dSAndy Fiddaman 			    attr->oa_linkid, aip->ai_name, aip->ai_val,
728faa2068dSAndy Fiddaman 			    aip->ai_count);
729faa2068dSAndy Fiddaman 			if (status != DLADM_STATUS_OK) {
730faa2068dSAndy Fiddaman 				(void) dladm_errlist_append(errs, "failed to "
731faa2068dSAndy Fiddaman 				    "persistently set varpd prop: %s\n",
732faa2068dSAndy Fiddaman 				    aip->ai_name);
733faa2068dSAndy Fiddaman 				(void) libvarpd_c_instance_destroy(vch, id);
734faa2068dSAndy Fiddaman 				libvarpd_c_destroy(vch);
735faa2068dSAndy Fiddaman 				return (status);
736faa2068dSAndy Fiddaman 			}
737faa2068dSAndy Fiddaman 		}
73836589d6bSRobert Mustacchi 	}
73936589d6bSRobert Mustacchi 
74036589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_activate(vch, id)) != 0) {
74136589d6bSRobert Mustacchi 		(void) dladm_errlist_append(errs,
74236589d6bSRobert Mustacchi 		    "failed to activate varpd instance: %s", strerror(ret));
743faa2068dSAndy Fiddaman 		(void) dladm_overlay_walk_varpd_prop(handle, attr->oa_linkid,
744faa2068dSAndy Fiddaman 		    id, dladm_overlay_activate_cb, errs);
74536589d6bSRobert Mustacchi 		(void) libvarpd_c_instance_destroy(vch, id);
74636589d6bSRobert Mustacchi 		libvarpd_c_destroy(vch);
74736589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
74836589d6bSRobert Mustacchi 
74936589d6bSRobert Mustacchi 	}
75036589d6bSRobert Mustacchi 
75136589d6bSRobert Mustacchi 	bzero(&oia, sizeof (oia));
752faa2068dSAndy Fiddaman 	oia.oia_linkid = attr->oa_linkid;
75336589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
75436589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_ACTIVATE, &oia);
75536589d6bSRobert Mustacchi 	if (ret != 0) {
75636589d6bSRobert Mustacchi 		ret = errno;
75736589d6bSRobert Mustacchi 		(void) dladm_errlist_append(errs, "failed to activate "
75836589d6bSRobert Mustacchi 		    "device: %s", strerror(ret));
75936589d6bSRobert Mustacchi 		(void) libvarpd_c_instance_destroy(vch, id);
760faa2068dSAndy Fiddaman 		(void) dladm_overlay_walk_prop(handle, attr->oa_linkid,
76136589d6bSRobert Mustacchi 		    dladm_overlay_activate_cb, errs, errs);
76236589d6bSRobert Mustacchi 		status = dladm_errno2status(ret);
76336589d6bSRobert Mustacchi 	}
76436589d6bSRobert Mustacchi 
76536589d6bSRobert Mustacchi 	libvarpd_c_destroy(vch);
76636589d6bSRobert Mustacchi 
76736589d6bSRobert Mustacchi 	return (status);
76836589d6bSRobert Mustacchi }
76936589d6bSRobert Mustacchi 
770faa2068dSAndy Fiddaman dladm_status_t
dladm_overlay_create(dladm_handle_t handle,const char * name,const char * encap,const char * search,uint64_t vid,dladm_arg_list_t * props,dladm_errlist_t * errs,uint32_t flags)771faa2068dSAndy Fiddaman dladm_overlay_create(dladm_handle_t handle, const char *name,
772faa2068dSAndy Fiddaman     const char *encap, const char *search, uint64_t vid,
773faa2068dSAndy Fiddaman     dladm_arg_list_t *props, dladm_errlist_t *errs, uint32_t flags)
774faa2068dSAndy Fiddaman {
775faa2068dSAndy Fiddaman 	dladm_status_t status;
776faa2068dSAndy Fiddaman 	datalink_id_t linkid;
777faa2068dSAndy Fiddaman 	dladm_overlay_attr_t attr;
778faa2068dSAndy Fiddaman 	char errmsg[DLADM_STRSIZE];
779faa2068dSAndy Fiddaman 
780faa2068dSAndy Fiddaman 	if (strlcpy(attr.oa_name, name, sizeof (attr.oa_name)) >=
781faa2068dSAndy Fiddaman 	    sizeof (attr.oa_name)) {
782faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
783faa2068dSAndy Fiddaman 	}
784faa2068dSAndy Fiddaman 	if (strlcpy(attr.oa_encap, encap, sizeof (attr.oa_encap)) >=
785faa2068dSAndy Fiddaman 	    sizeof (attr.oa_encap)) {
786faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
787faa2068dSAndy Fiddaman 	}
788faa2068dSAndy Fiddaman 	if (strlcpy(attr.oa_search, search, sizeof (attr.oa_search)) >=
789faa2068dSAndy Fiddaman 	    sizeof (attr.oa_search)) {
790faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
791faa2068dSAndy Fiddaman 	}
792faa2068dSAndy Fiddaman 
793faa2068dSAndy Fiddaman 	status = varpd_enable_service();
794faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
795faa2068dSAndy Fiddaman 		return (status);
796faa2068dSAndy Fiddaman 
797faa2068dSAndy Fiddaman 	status = dladm_create_datalink_id(handle, name, DATALINK_CLASS_OVERLAY,
798faa2068dSAndy Fiddaman 	    DL_ETHER, flags, &linkid);
799faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
800faa2068dSAndy Fiddaman 		return (status);
801faa2068dSAndy Fiddaman 
802faa2068dSAndy Fiddaman 	attr.oa_linkid = linkid;
803faa2068dSAndy Fiddaman 	attr.oa_vid = vid;
804faa2068dSAndy Fiddaman 	attr.oa_flags = flags;
805faa2068dSAndy Fiddaman 
806faa2068dSAndy Fiddaman 	status = i_dladm_overlay_create_sys(handle, &attr);
807faa2068dSAndy Fiddaman 
808faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
809faa2068dSAndy Fiddaman 		(void) dladm_destroy_datalink_id(handle, linkid, flags);
810faa2068dSAndy Fiddaman 		return (status);
811faa2068dSAndy Fiddaman 	}
812faa2068dSAndy Fiddaman 
813faa2068dSAndy Fiddaman 	if ((flags & DLADM_OPT_PERSIST) != 0) {
814faa2068dSAndy Fiddaman 		status = dladm_overlay_persist_config(handle, &attr);
815faa2068dSAndy Fiddaman 		if (status != DLADM_STATUS_OK) {
816faa2068dSAndy Fiddaman 			(void) dladm_errlist_append(errs, "failed to create "
817faa2068dSAndy Fiddaman 			    "persistent configuration for %s: %s",
818faa2068dSAndy Fiddaman 			    attr.oa_name, dladm_status2str(status, errmsg));
819faa2068dSAndy Fiddaman 		}
820faa2068dSAndy Fiddaman 	}
821faa2068dSAndy Fiddaman 
822faa2068dSAndy Fiddaman 	if (status == DLADM_STATUS_OK)
823faa2068dSAndy Fiddaman 		status = i_dladm_overlay_commit_sys(handle, &attr, props, errs);
824faa2068dSAndy Fiddaman 
825faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
826faa2068dSAndy Fiddaman 		(void) dladm_overlay_delete(handle, linkid, flags);
827faa2068dSAndy Fiddaman 		(void) dladm_destroy_datalink_id(handle, linkid, flags);
828faa2068dSAndy Fiddaman 	}
82936589d6bSRobert Mustacchi 
830faa2068dSAndy Fiddaman 	return (status);
831faa2068dSAndy Fiddaman }
83236589d6bSRobert Mustacchi 
83336589d6bSRobert Mustacchi typedef struct overlay_walk_cb {
83436589d6bSRobert Mustacchi 	dladm_handle_t		owc_handle;
83536589d6bSRobert Mustacchi 	datalink_id_t		owc_linkid;
83636589d6bSRobert Mustacchi 	void			*owc_arg;
83736589d6bSRobert Mustacchi 	dladm_overlay_cache_f	owc_func;
83836589d6bSRobert Mustacchi 	uint_t			owc_mode;
83936589d6bSRobert Mustacchi 	uint_t			owc_dest;
84036589d6bSRobert Mustacchi } overlay_walk_cb_t;
84136589d6bSRobert Mustacchi 
84236589d6bSRobert Mustacchi static int
dladm_overlay_walk_cache_cb(varpd_client_handle_t * chdl __unused,uint64_t varpdid __unused,const struct ether_addr * key,const varpd_client_cache_entry_t * entry,void * arg)84320535e13SToomas Soome dladm_overlay_walk_cache_cb(varpd_client_handle_t *chdl __unused,
84420535e13SToomas Soome     uint64_t varpdid __unused, const struct ether_addr *key,
84520535e13SToomas Soome     const varpd_client_cache_entry_t *entry, void *arg)
84636589d6bSRobert Mustacchi {
84736589d6bSRobert Mustacchi 	overlay_walk_cb_t *owc = arg;
84836589d6bSRobert Mustacchi 	dladm_overlay_point_t point;
84936589d6bSRobert Mustacchi 
85036589d6bSRobert Mustacchi 	bzero(&point, sizeof (dladm_overlay_point_t));
85136589d6bSRobert Mustacchi 	point.dop_dest = owc->owc_dest;
85236589d6bSRobert Mustacchi 	point.dop_mac = entry->vcp_mac;
85336589d6bSRobert Mustacchi 	point.dop_flags = entry->vcp_flags;
85436589d6bSRobert Mustacchi 	point.dop_ip = entry->vcp_ip;
85536589d6bSRobert Mustacchi 	point.dop_port = entry->vcp_port;
85636589d6bSRobert Mustacchi 
85736589d6bSRobert Mustacchi 	if (owc->owc_mode == OVERLAY_TARGET_POINT)
85836589d6bSRobert Mustacchi 		point.dop_flags |= DLADM_OVERLAY_F_DEFAULT;
85936589d6bSRobert Mustacchi 
86036589d6bSRobert Mustacchi 	if (owc->owc_func(owc->owc_handle, owc->owc_linkid, key, &point,
86136589d6bSRobert Mustacchi 	    owc->owc_arg) == DLADM_WALK_TERMINATE)
86236589d6bSRobert Mustacchi 		return (1);
86336589d6bSRobert Mustacchi 	return (0);
86436589d6bSRobert Mustacchi }
86536589d6bSRobert Mustacchi 
86636589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_walk_cache(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_cache_f func,void * arg)86736589d6bSRobert Mustacchi dladm_overlay_walk_cache(dladm_handle_t handle, datalink_id_t linkid,
86836589d6bSRobert Mustacchi     dladm_overlay_cache_f func, void *arg)
86936589d6bSRobert Mustacchi {
87036589d6bSRobert Mustacchi 	int ret;
87136589d6bSRobert Mustacchi 	uint_t mode, dest;
87236589d6bSRobert Mustacchi 	uint64_t varpdid;
87336589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
87436589d6bSRobert Mustacchi 	overlay_walk_cb_t cbarg;
87536589d6bSRobert Mustacchi 
87636589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
87736589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
87836589d6bSRobert Mustacchi 
87936589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
88036589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
88136589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
88236589d6bSRobert Mustacchi 	}
88336589d6bSRobert Mustacchi 
88436589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_target_mode(chdl, varpdid,
88536589d6bSRobert Mustacchi 	    &dest, &mode)) != 0) {
88636589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
88736589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
88836589d6bSRobert Mustacchi 	}
88936589d6bSRobert Mustacchi 
89036589d6bSRobert Mustacchi 	cbarg.owc_handle = handle;
89136589d6bSRobert Mustacchi 	cbarg.owc_linkid = linkid;
89236589d6bSRobert Mustacchi 	cbarg.owc_arg = arg;
89336589d6bSRobert Mustacchi 	cbarg.owc_func = func;
89436589d6bSRobert Mustacchi 	cbarg.owc_dest = dest;
89536589d6bSRobert Mustacchi 	cbarg.owc_mode = mode;
89636589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_cache_walk(chdl, varpdid,
89736589d6bSRobert Mustacchi 	    dladm_overlay_walk_cache_cb, &cbarg);
89836589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
89936589d6bSRobert Mustacchi 
90036589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
90136589d6bSRobert Mustacchi }
90236589d6bSRobert Mustacchi 
90336589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_cache_flush(dladm_handle_t handle __unused,datalink_id_t linkid)90420535e13SToomas Soome dladm_overlay_cache_flush(dladm_handle_t handle __unused, datalink_id_t linkid)
90536589d6bSRobert Mustacchi {
90636589d6bSRobert Mustacchi 	int ret;
90736589d6bSRobert Mustacchi 	uint64_t varpdid;
90836589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
90936589d6bSRobert Mustacchi 
91036589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
91136589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
91236589d6bSRobert Mustacchi 
91336589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
91436589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
91536589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
91636589d6bSRobert Mustacchi 	}
91736589d6bSRobert Mustacchi 
91836589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_cache_flush(chdl, varpdid);
91936589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
92036589d6bSRobert Mustacchi 
92136589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
92236589d6bSRobert Mustacchi }
92336589d6bSRobert Mustacchi 
92436589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_cache_delete(dladm_handle_t handle __unused,datalink_id_t linkid,const struct ether_addr * key)92520535e13SToomas Soome dladm_overlay_cache_delete(dladm_handle_t handle __unused, datalink_id_t linkid,
92636589d6bSRobert Mustacchi     const struct ether_addr *key)
92736589d6bSRobert Mustacchi {
92836589d6bSRobert Mustacchi 	int ret;
92936589d6bSRobert Mustacchi 	uint64_t varpdid;
93036589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
93136589d6bSRobert Mustacchi 
93236589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
93336589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
93436589d6bSRobert Mustacchi 
93536589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
93636589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
93736589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
93836589d6bSRobert Mustacchi 	}
93936589d6bSRobert Mustacchi 
94036589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_cache_delete(chdl, varpdid, key);
94136589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
94236589d6bSRobert Mustacchi 
94336589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
94436589d6bSRobert Mustacchi }
94536589d6bSRobert Mustacchi 
94636589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_cache_set(dladm_handle_t handle __unused,datalink_id_t linkid,const struct ether_addr * key,char * val)94720535e13SToomas Soome dladm_overlay_cache_set(dladm_handle_t handle __unused, datalink_id_t linkid,
94836589d6bSRobert Mustacchi     const struct ether_addr *key, char *val)
94936589d6bSRobert Mustacchi {
95036589d6bSRobert Mustacchi 	int ret;
95136589d6bSRobert Mustacchi 	uint_t dest;
95236589d6bSRobert Mustacchi 	uint64_t varpdid;
95336589d6bSRobert Mustacchi 	char *ip, *port = NULL;
95436589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
95536589d6bSRobert Mustacchi 	varpd_client_cache_entry_t vcp;
95636589d6bSRobert Mustacchi 
95736589d6bSRobert Mustacchi 
95836589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
95936589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
96036589d6bSRobert Mustacchi 
96136589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
96236589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
96336589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
96436589d6bSRobert Mustacchi 	}
96536589d6bSRobert Mustacchi 
96636589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_target_mode(chdl, varpdid,
96736589d6bSRobert Mustacchi 	    &dest, NULL)) != 0) {
96836589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
96936589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
97036589d6bSRobert Mustacchi 	}
97136589d6bSRobert Mustacchi 
97236589d6bSRobert Mustacchi 	/*
97336589d6bSRobert Mustacchi 	 * Mode tells us what we should expect in val. It we have more than one
97436589d6bSRobert Mustacchi 	 * thing listed, the canonical format of it right now is mac,ip:port.
97536589d6bSRobert Mustacchi 	 */
97636589d6bSRobert Mustacchi 	bzero(&vcp, sizeof (varpd_client_cache_entry_t));
97736589d6bSRobert Mustacchi 
97836589d6bSRobert Mustacchi 	if (strcasecmp(val, "drop") == 0) {
97936589d6bSRobert Mustacchi 		vcp.vcp_flags = OVERLAY_TARGET_CACHE_DROP;
98036589d6bSRobert Mustacchi 		goto send;
98136589d6bSRobert Mustacchi 	}
98236589d6bSRobert Mustacchi 
98336589d6bSRobert Mustacchi 	if (dest & OVERLAY_PLUGIN_D_ETHERNET) {
98436589d6bSRobert Mustacchi 		if (ether_aton_r(val, &vcp.vcp_mac) == NULL) {
98536589d6bSRobert Mustacchi 			libvarpd_c_destroy(chdl);
98636589d6bSRobert Mustacchi 			return (dladm_errno2status(EINVAL));
98736589d6bSRobert Mustacchi 		}
98836589d6bSRobert Mustacchi 	}
98936589d6bSRobert Mustacchi 
99036589d6bSRobert Mustacchi 	if (dest & OVERLAY_PLUGIN_D_IP) {
99136589d6bSRobert Mustacchi 		if (dest & OVERLAY_PLUGIN_D_ETHERNET) {
99236589d6bSRobert Mustacchi 			if ((ip = strchr(val, ',')) == NULL) {
99336589d6bSRobert Mustacchi 				libvarpd_c_destroy(chdl);
99436589d6bSRobert Mustacchi 				return (dladm_errno2status(ret));
99536589d6bSRobert Mustacchi 			}
99636589d6bSRobert Mustacchi 			ip++;
99736589d6bSRobert Mustacchi 		} else {
99836589d6bSRobert Mustacchi 			ip = val;
99936589d6bSRobert Mustacchi 		}
100036589d6bSRobert Mustacchi 
100136589d6bSRobert Mustacchi 		if (dest & OVERLAY_PLUGIN_D_PORT) {
100236589d6bSRobert Mustacchi 			if ((port = strchr(val, ':')) == NULL) {
100336589d6bSRobert Mustacchi 				libvarpd_c_destroy(chdl);
100436589d6bSRobert Mustacchi 				return (dladm_errno2status(ret));
100536589d6bSRobert Mustacchi 			}
100636589d6bSRobert Mustacchi 			*port = '\0';
100736589d6bSRobert Mustacchi 			port++;
100836589d6bSRobert Mustacchi 		}
100936589d6bSRobert Mustacchi 
101036589d6bSRobert Mustacchi 		/* Try v6, then fall back to v4 */
101136589d6bSRobert Mustacchi 		ret = inet_pton(AF_INET6, ip, &vcp.vcp_ip);
101236589d6bSRobert Mustacchi 		if (ret == -1)
101336589d6bSRobert Mustacchi 			abort();
101436589d6bSRobert Mustacchi 		if (ret == 0) {
101536589d6bSRobert Mustacchi 			struct in_addr v4;
101636589d6bSRobert Mustacchi 
101736589d6bSRobert Mustacchi 			ret = inet_pton(AF_INET, ip, &v4);
101836589d6bSRobert Mustacchi 			if (ret == -1)
101936589d6bSRobert Mustacchi 				abort();
102036589d6bSRobert Mustacchi 			if (ret == 0) {
102136589d6bSRobert Mustacchi 				libvarpd_c_destroy(chdl);
102236589d6bSRobert Mustacchi 				return (dladm_errno2status(ret));
102336589d6bSRobert Mustacchi 			}
102436589d6bSRobert Mustacchi 			IN6_INADDR_TO_V4MAPPED(&v4, &vcp.vcp_ip);
102536589d6bSRobert Mustacchi 		}
102636589d6bSRobert Mustacchi 	}
102736589d6bSRobert Mustacchi 
102836589d6bSRobert Mustacchi 	if (dest & OVERLAY_PLUGIN_D_PORT) {
102936589d6bSRobert Mustacchi 		char *eptr;
103036589d6bSRobert Mustacchi 		unsigned long l;
103136589d6bSRobert Mustacchi 		if (port == NULL && (dest & OVERLAY_PLUGIN_D_ETHERNET)) {
103236589d6bSRobert Mustacchi 			if ((port = strchr(val, ',')) == NULL) {
103336589d6bSRobert Mustacchi 				libvarpd_c_destroy(chdl);
103436589d6bSRobert Mustacchi 				return (dladm_errno2status(EINVAL));
103536589d6bSRobert Mustacchi 			}
103636589d6bSRobert Mustacchi 		} else if (port == NULL)
103736589d6bSRobert Mustacchi 			port = val;
103836589d6bSRobert Mustacchi 
103936589d6bSRobert Mustacchi 		errno = 0;
104036589d6bSRobert Mustacchi 		l = strtoul(port, &eptr, 10);
104136589d6bSRobert Mustacchi 		if (errno != 0 || *eptr != '\0') {
104236589d6bSRobert Mustacchi 			libvarpd_c_destroy(chdl);
104336589d6bSRobert Mustacchi 			return (dladm_errno2status(EINVAL));
104436589d6bSRobert Mustacchi 		}
104536589d6bSRobert Mustacchi 		if (l == 0 || l > UINT16_MAX) {
104636589d6bSRobert Mustacchi 			libvarpd_c_destroy(chdl);
104736589d6bSRobert Mustacchi 			return (dladm_errno2status(EINVAL));
104836589d6bSRobert Mustacchi 		}
104936589d6bSRobert Mustacchi 		vcp.vcp_port = l;
105036589d6bSRobert Mustacchi 	}
105136589d6bSRobert Mustacchi 
105236589d6bSRobert Mustacchi send:
105336589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_cache_set(chdl, varpdid, key, &vcp);
105436589d6bSRobert Mustacchi 
105536589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
105636589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
105736589d6bSRobert Mustacchi }
105836589d6bSRobert Mustacchi 
105936589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_cache_get(dladm_handle_t handle __unused,datalink_id_t linkid,const struct ether_addr * key,dladm_overlay_point_t * point)106020535e13SToomas Soome dladm_overlay_cache_get(dladm_handle_t handle __unused, datalink_id_t linkid,
106136589d6bSRobert Mustacchi     const struct ether_addr *key, dladm_overlay_point_t *point)
106236589d6bSRobert Mustacchi {
106336589d6bSRobert Mustacchi 	int ret;
106436589d6bSRobert Mustacchi 	uint_t dest, mode;
106536589d6bSRobert Mustacchi 	uint64_t varpdid;
106636589d6bSRobert Mustacchi 	varpd_client_handle_t *chdl;
106736589d6bSRobert Mustacchi 	varpd_client_cache_entry_t entry;
106836589d6bSRobert Mustacchi 
106936589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_create(&chdl, dladm_overlay_doorpath)) != 0)
107036589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
107136589d6bSRobert Mustacchi 
107236589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_lookup(chdl, linkid, &varpdid)) != 0) {
107336589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
107436589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
107536589d6bSRobert Mustacchi 	}
107636589d6bSRobert Mustacchi 
107736589d6bSRobert Mustacchi 	if ((ret = libvarpd_c_instance_target_mode(chdl, varpdid,
107836589d6bSRobert Mustacchi 	    &dest, &mode)) != 0) {
107936589d6bSRobert Mustacchi 		libvarpd_c_destroy(chdl);
108036589d6bSRobert Mustacchi 		return (dladm_errno2status(ret));
108136589d6bSRobert Mustacchi 	}
108236589d6bSRobert Mustacchi 
108336589d6bSRobert Mustacchi 	ret = libvarpd_c_instance_cache_get(chdl, varpdid, key, &entry);
108436589d6bSRobert Mustacchi 	if (ret == 0) {
108536589d6bSRobert Mustacchi 		point->dop_dest = dest;
108636589d6bSRobert Mustacchi 		point->dop_mac = entry.vcp_mac;
108736589d6bSRobert Mustacchi 		point->dop_flags = entry.vcp_flags;
108836589d6bSRobert Mustacchi 		point->dop_ip = entry.vcp_ip;
108936589d6bSRobert Mustacchi 		point->dop_port = entry.vcp_port;
109036589d6bSRobert Mustacchi 		if (mode == OVERLAY_TARGET_POINT)
109136589d6bSRobert Mustacchi 			point->dop_flags |= DLADM_OVERLAY_F_DEFAULT;
109236589d6bSRobert Mustacchi 	}
109336589d6bSRobert Mustacchi 
109436589d6bSRobert Mustacchi 	libvarpd_c_destroy(chdl);
109536589d6bSRobert Mustacchi 	return (dladm_errno2status(ret));
109636589d6bSRobert Mustacchi }
109736589d6bSRobert Mustacchi 
109836589d6bSRobert Mustacchi dladm_status_t
dladm_overlay_status(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_status_f func,void * arg)109936589d6bSRobert Mustacchi dladm_overlay_status(dladm_handle_t handle, datalink_id_t linkid,
110036589d6bSRobert Mustacchi     dladm_overlay_status_f func, void *arg)
110136589d6bSRobert Mustacchi {
110236589d6bSRobert Mustacchi 	int ret;
110336589d6bSRobert Mustacchi 	dladm_status_t status;
110436589d6bSRobert Mustacchi 	overlay_ioc_status_t ois;
110536589d6bSRobert Mustacchi 	dladm_overlay_status_t dos;
110636589d6bSRobert Mustacchi 
110736589d6bSRobert Mustacchi 	ois.ois_linkid = linkid;
110836589d6bSRobert Mustacchi 	status = DLADM_STATUS_OK;
110936589d6bSRobert Mustacchi 	ret = ioctl(dladm_dld_fd(handle), OVERLAY_IOC_STATUS, &ois);
111036589d6bSRobert Mustacchi 	if (ret != 0)
111136589d6bSRobert Mustacchi 		status = dladm_errno2status(errno);
111236589d6bSRobert Mustacchi 	if (status != DLADM_STATUS_OK)
111336589d6bSRobert Mustacchi 		return (status);
111436589d6bSRobert Mustacchi 
111536589d6bSRobert Mustacchi 	dos.dos_degraded = ois.ois_status == OVERLAY_I_DEGRADED ? B_TRUE :
111636589d6bSRobert Mustacchi 	    B_FALSE;
111736589d6bSRobert Mustacchi 	(void) strlcpy(dos.dos_fmamsg, ois.ois_message,
111836589d6bSRobert Mustacchi 	    sizeof (dos.dos_fmamsg));
111936589d6bSRobert Mustacchi 	func(handle, linkid, &dos, arg);
112036589d6bSRobert Mustacchi 	return (DLADM_STATUS_OK);
112136589d6bSRobert Mustacchi }
1122faa2068dSAndy Fiddaman 
1123faa2068dSAndy Fiddaman /*
1124faa2068dSAndy Fiddaman  * dladm_parse_args() usually creates a dladm_arg_list_t by tokenising a
1125faa2068dSAndy Fiddaman  * delimited string and storing pointers to pieces of that string in the
1126faa2068dSAndy Fiddaman  * dladm_arg_info_t structure. Those pointers do not need to be individually
1127faa2068dSAndy Fiddaman  * freed.
1128faa2068dSAndy Fiddaman  *
1129faa2068dSAndy Fiddaman  * This function deals with property lists which have instead been built from
1130faa2068dSAndy Fiddaman  * the persistent datalink configuration database, in order to bring up an
1131faa2068dSAndy Fiddaman  * overlay at boot time. In this case, the properties have been retrieved
1132faa2068dSAndy Fiddaman  * one-by-one, duplicated with strdup(), and added to the list. When the list
1133faa2068dSAndy Fiddaman  * is finished with, this function takes care of freeing the memory.
1134faa2068dSAndy Fiddaman  */
1135faa2068dSAndy Fiddaman static void
i_dladm_overlay_props_free(dladm_handle_t handle __unused,dladm_arg_list_t * props)113620535e13SToomas Soome i_dladm_overlay_props_free(dladm_handle_t handle __unused,
113720535e13SToomas Soome     dladm_arg_list_t *props)
1138faa2068dSAndy Fiddaman {
1139faa2068dSAndy Fiddaman 	uint_t i, j;
1140faa2068dSAndy Fiddaman 
1141faa2068dSAndy Fiddaman 	for (i = 0; props != NULL && i < props->al_count; i++) {
1142faa2068dSAndy Fiddaman 		dladm_arg_info_t *aip = &props->al_info[i];
1143faa2068dSAndy Fiddaman 
1144faa2068dSAndy Fiddaman 		/* For ai_name, we need to cast away the 'const' qualifier. */
1145faa2068dSAndy Fiddaman 		free((char *)aip->ai_name);
1146faa2068dSAndy Fiddaman 		for (j = 0; j < aip->ai_count; j++)
1147faa2068dSAndy Fiddaman 			free(aip->ai_val[j]);
1148faa2068dSAndy Fiddaman 	}
1149faa2068dSAndy Fiddaman 	free(props);
1150faa2068dSAndy Fiddaman }
1151faa2068dSAndy Fiddaman 
1152faa2068dSAndy Fiddaman static dladm_status_t
i_dladm_overlay_fetch_persistent_config(dladm_handle_t handle,datalink_id_t linkid,dladm_overlay_attr_t * attrp,dladm_arg_list_t ** props)1153faa2068dSAndy Fiddaman i_dladm_overlay_fetch_persistent_config(dladm_handle_t handle,
1154faa2068dSAndy Fiddaman     datalink_id_t linkid, dladm_overlay_attr_t *attrp,
1155faa2068dSAndy Fiddaman     dladm_arg_list_t **props)
1156faa2068dSAndy Fiddaman {
1157faa2068dSAndy Fiddaman 	dladm_conf_t conf;
1158faa2068dSAndy Fiddaman 	dladm_status_t status;
1159faa2068dSAndy Fiddaman 	char attr[MAXLINKATTRLEN], last_attr[MAXLINKATTRLEN];
1160faa2068dSAndy Fiddaman 	char attrval[OVERLAY_PROP_SIZEMAX];
1161faa2068dSAndy Fiddaman 	size_t attrsz;
1162faa2068dSAndy Fiddaman 	dladm_arg_list_t *list = NULL;
1163faa2068dSAndy Fiddaman 
1164faa2068dSAndy Fiddaman 	*props = NULL;
1165faa2068dSAndy Fiddaman 
1166faa2068dSAndy Fiddaman 	if ((status = dladm_getsnap_conf(handle, linkid, &conf)) !=
1167faa2068dSAndy Fiddaman 	    DLADM_STATUS_OK) {
1168faa2068dSAndy Fiddaman 		return (status);
1169faa2068dSAndy Fiddaman 	}
1170faa2068dSAndy Fiddaman 
1171faa2068dSAndy Fiddaman 	attrp->oa_linkid = linkid;
1172faa2068dSAndy Fiddaman 
1173faa2068dSAndy Fiddaman 	status = dladm_get_conf_field(handle, conf, FVNETID, &attrp->oa_vid,
1174faa2068dSAndy Fiddaman 	    sizeof (attrp->oa_vid));
1175faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
1176faa2068dSAndy Fiddaman 		goto done;
1177faa2068dSAndy Fiddaman 
1178faa2068dSAndy Fiddaman 	status = dladm_get_conf_field(handle, conf, FENCAP,
1179faa2068dSAndy Fiddaman 	    attrp->oa_encap, sizeof (attrp->oa_encap));
1180faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
1181faa2068dSAndy Fiddaman 		goto done;
1182faa2068dSAndy Fiddaman 
1183faa2068dSAndy Fiddaman 	status = dladm_get_conf_field(handle, conf, FSEARCH,
1184faa2068dSAndy Fiddaman 	    attrp->oa_search, sizeof (attrp->oa_search));
1185faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK)
1186faa2068dSAndy Fiddaman 		goto done;
1187faa2068dSAndy Fiddaman 
1188faa2068dSAndy Fiddaman 	list = calloc(1, sizeof (dladm_arg_list_t));
1189faa2068dSAndy Fiddaman 
1190faa2068dSAndy Fiddaman 	*last_attr = '\0';
1191faa2068dSAndy Fiddaman 	while (dladm_getnext_conf_linkprop(handle, conf, last_attr,
1192faa2068dSAndy Fiddaman 	    attr, attrval, sizeof (attrval), &attrsz) == DLADM_STATUS_OK) {
1193faa2068dSAndy Fiddaman 		dladm_arg_info_t *aip;
1194faa2068dSAndy Fiddaman 
1195faa2068dSAndy Fiddaman 		(void) strlcpy(last_attr, attr, sizeof (last_attr));
1196faa2068dSAndy Fiddaman 		if (strchr(attr, '/') == NULL)
1197faa2068dSAndy Fiddaman 			continue;
1198faa2068dSAndy Fiddaman 
1199faa2068dSAndy Fiddaman 		aip = &list->al_info[list->al_count];
1200faa2068dSAndy Fiddaman 		bzero(aip, sizeof (dladm_arg_info_t));
1201faa2068dSAndy Fiddaman 		if ((aip->ai_name = strdup(attr)) == NULL) {
1202faa2068dSAndy Fiddaman 			status = dladm_errno2status(errno);
1203faa2068dSAndy Fiddaman 			break;
1204faa2068dSAndy Fiddaman 		}
1205faa2068dSAndy Fiddaman 		if ((aip->ai_val[0] = strdup(attrval)) == NULL) {
1206faa2068dSAndy Fiddaman 			status = dladm_errno2status(errno);
1207faa2068dSAndy Fiddaman 			break;
1208faa2068dSAndy Fiddaman 		}
1209faa2068dSAndy Fiddaman 		aip->ai_count = 1;
1210faa2068dSAndy Fiddaman 		list->al_count++;
1211faa2068dSAndy Fiddaman 		if (list->al_count >= DLADM_MAX_ARG_CNT) {
1212faa2068dSAndy Fiddaman 			status = DLADM_STATUS_TOOMANYELEMENTS;
1213faa2068dSAndy Fiddaman 			break;
1214faa2068dSAndy Fiddaman 		}
1215faa2068dSAndy Fiddaman 	}
1216faa2068dSAndy Fiddaman 
1217faa2068dSAndy Fiddaman done:
1218faa2068dSAndy Fiddaman 
1219faa2068dSAndy Fiddaman 	dladm_destroy_conf(handle, conf);
1220faa2068dSAndy Fiddaman 
1221faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1222faa2068dSAndy Fiddaman 		if (list != NULL)
1223faa2068dSAndy Fiddaman 			i_dladm_overlay_props_free(handle, list);
1224faa2068dSAndy Fiddaman 		return (status);
1225faa2068dSAndy Fiddaman 	}
1226faa2068dSAndy Fiddaman 
1227faa2068dSAndy Fiddaman 	*props = list;
1228faa2068dSAndy Fiddaman 	return (DLADM_STATUS_OK);
1229faa2068dSAndy Fiddaman }
1230faa2068dSAndy Fiddaman 
1231faa2068dSAndy Fiddaman typedef struct dladm_overlay_up_arg_s {
1232faa2068dSAndy Fiddaman 	dladm_errlist_t	*errlist;
1233faa2068dSAndy Fiddaman } dladm_overlay_up_arg_t;
1234faa2068dSAndy Fiddaman 
1235faa2068dSAndy Fiddaman static int
i_dladm_overlay_up(dladm_handle_t handle,datalink_id_t linkid,void * arg)1236faa2068dSAndy Fiddaman i_dladm_overlay_up(dladm_handle_t handle, datalink_id_t linkid, void *arg)
1237faa2068dSAndy Fiddaman {
1238faa2068dSAndy Fiddaman 	dladm_overlay_up_arg_t *argp = arg;
1239faa2068dSAndy Fiddaman 	dladm_errlist_t *errs = argp->errlist;
1240faa2068dSAndy Fiddaman 	datalink_class_t class;
1241faa2068dSAndy Fiddaman 	dladm_status_t status;
1242faa2068dSAndy Fiddaman 	dladm_overlay_attr_t attr;
1243faa2068dSAndy Fiddaman 	dladm_arg_list_t *props;
1244faa2068dSAndy Fiddaman 	char errmsg[DLADM_STRSIZE];
1245faa2068dSAndy Fiddaman 
1246faa2068dSAndy Fiddaman 	bzero(&attr, sizeof (attr));
1247faa2068dSAndy Fiddaman 
1248faa2068dSAndy Fiddaman 	status = dladm_datalink_id2info(handle, linkid, NULL, &class,
1249faa2068dSAndy Fiddaman 	    NULL, attr.oa_name, sizeof (attr.oa_name));
1250faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1251faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs, "failed to get info for "
1252faa2068dSAndy Fiddaman 		    "datalink id %u: %s",
1253faa2068dSAndy Fiddaman 		    linkid, dladm_status2str(status, errmsg));
1254faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
1255faa2068dSAndy Fiddaman 	}
1256faa2068dSAndy Fiddaman 
1257faa2068dSAndy Fiddaman 	if (class != DATALINK_CLASS_OVERLAY) {
1258faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs, "%s is not an overlay",
1259faa2068dSAndy Fiddaman 		    attr.oa_name);
1260faa2068dSAndy Fiddaman 		return (DLADM_STATUS_BADARG);
1261faa2068dSAndy Fiddaman 	}
1262faa2068dSAndy Fiddaman 
1263faa2068dSAndy Fiddaman 	status = varpd_enable_service();
1264faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1265faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs, "failed to enable svc:/%s",
1266faa2068dSAndy Fiddaman 		    VARPD_SERVICE);
1267faa2068dSAndy Fiddaman 		return (DLADM_WALK_TERMINATE);
1268faa2068dSAndy Fiddaman 	}
1269faa2068dSAndy Fiddaman 
1270faa2068dSAndy Fiddaman 	status = i_dladm_overlay_fetch_persistent_config(handle, linkid,
1271faa2068dSAndy Fiddaman 	    &attr, &props);
1272faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1273faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs, "failed to retrieve "
1274faa2068dSAndy Fiddaman 		    "persistent configuration for %s: %s",
1275faa2068dSAndy Fiddaman 		    attr.oa_name, dladm_status2str(status, errmsg));
1276faa2068dSAndy Fiddaman 		return (DLADM_WALK_CONTINUE);
1277faa2068dSAndy Fiddaman 	}
1278faa2068dSAndy Fiddaman 
1279faa2068dSAndy Fiddaman 	status = i_dladm_overlay_create_sys(handle, &attr);
1280faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1281faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs,
1282faa2068dSAndy Fiddaman 		    "failed to create overlay device %s: %s",
1283faa2068dSAndy Fiddaman 		    attr.oa_name, dladm_status2str(status, errmsg));
1284faa2068dSAndy Fiddaman 		goto out;
1285faa2068dSAndy Fiddaman 	}
1286faa2068dSAndy Fiddaman 
1287faa2068dSAndy Fiddaman 	status = i_dladm_overlay_commit_sys(handle, &attr, props, errs);
1288faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1289faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs,
1290faa2068dSAndy Fiddaman 		    "failed to set properties for overlay device %s: %s",
1291faa2068dSAndy Fiddaman 		    attr.oa_name, dladm_status2str(status, errmsg));
1292faa2068dSAndy Fiddaman 		dladm_overlay_delete(handle, linkid, 0);
1293faa2068dSAndy Fiddaman 		goto out;
1294faa2068dSAndy Fiddaman 	}
1295faa2068dSAndy Fiddaman 
1296faa2068dSAndy Fiddaman 	status = dladm_up_datalink_id(handle, linkid);
1297faa2068dSAndy Fiddaman 	if (status != DLADM_STATUS_OK) {
1298faa2068dSAndy Fiddaman 		(void) dladm_errlist_append(errs,
1299faa2068dSAndy Fiddaman 		    "failed to bring datalink up for overlay device %s: %s",
1300faa2068dSAndy Fiddaman 		    attr.oa_name, dladm_status2str(status, errmsg));
1301faa2068dSAndy Fiddaman 		dladm_overlay_delete(handle, linkid, 0);
1302faa2068dSAndy Fiddaman 		goto out;
1303faa2068dSAndy Fiddaman 	}
1304faa2068dSAndy Fiddaman 
1305faa2068dSAndy Fiddaman out:
1306faa2068dSAndy Fiddaman 	i_dladm_overlay_props_free(handle, props);
1307faa2068dSAndy Fiddaman 
1308faa2068dSAndy Fiddaman 	return (DLADM_WALK_CONTINUE);
1309faa2068dSAndy Fiddaman }
1310faa2068dSAndy Fiddaman 
1311faa2068dSAndy Fiddaman dladm_status_t
dladm_overlay_up(dladm_handle_t handle,datalink_id_t linkid,dladm_errlist_t * errs)1312faa2068dSAndy Fiddaman dladm_overlay_up(dladm_handle_t handle, datalink_id_t linkid,
1313faa2068dSAndy Fiddaman     dladm_errlist_t *errs)
1314faa2068dSAndy Fiddaman {
1315faa2068dSAndy Fiddaman 	dladm_overlay_up_arg_t overlay_arg = {
1316faa2068dSAndy Fiddaman 		.errlist	= errs
1317faa2068dSAndy Fiddaman 	};
1318faa2068dSAndy Fiddaman 
1319faa2068dSAndy Fiddaman 	if (linkid == DATALINK_ALL_LINKID) {
1320faa2068dSAndy Fiddaman 		(void) dladm_walk_datalink_id(i_dladm_overlay_up, handle,
1321faa2068dSAndy Fiddaman 		    &overlay_arg, DATALINK_CLASS_OVERLAY,
1322faa2068dSAndy Fiddaman 		    DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
1323faa2068dSAndy Fiddaman 	} else {
1324faa2068dSAndy Fiddaman 		(void) i_dladm_overlay_up(handle, linkid, &overlay_arg);
1325faa2068dSAndy Fiddaman 	}
1326faa2068dSAndy Fiddaman 
1327faa2068dSAndy Fiddaman 	if (dladm_errlist_count(errs) == 0)
1328faa2068dSAndy Fiddaman 		return (DLADM_STATUS_OK);
1329faa2068dSAndy Fiddaman 
1330faa2068dSAndy Fiddaman 	return (DLADM_STATUS_FAILED);
1331faa2068dSAndy Fiddaman }
1332