xref: /titanic_50/usr/src/lib/libdladm/common/libdliptun.c (revision 2b24ab6b3865caeede9eeb9db6b83e1d89dcd1ea)
1*2b24ab6bSSebastien Roy /*
2*2b24ab6bSSebastien Roy  * CDDL HEADER START
3*2b24ab6bSSebastien Roy  *
4*2b24ab6bSSebastien Roy  * The contents of this file are subject to the terms of the
5*2b24ab6bSSebastien Roy  * Common Development and Distribution License (the "License").
6*2b24ab6bSSebastien Roy  * You may not use this file except in compliance with the License.
7*2b24ab6bSSebastien Roy  *
8*2b24ab6bSSebastien Roy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2b24ab6bSSebastien Roy  * or http://www.opensolaris.org/os/licensing.
10*2b24ab6bSSebastien Roy  * See the License for the specific language governing permissions
11*2b24ab6bSSebastien Roy  * and limitations under the License.
12*2b24ab6bSSebastien Roy  *
13*2b24ab6bSSebastien Roy  * When distributing Covered Code, include this CDDL HEADER in each
14*2b24ab6bSSebastien Roy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2b24ab6bSSebastien Roy  * If applicable, add the following below this CDDL HEADER, with the
16*2b24ab6bSSebastien Roy  * fields enclosed by brackets "[]" replaced with your own identifying
17*2b24ab6bSSebastien Roy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2b24ab6bSSebastien Roy  *
19*2b24ab6bSSebastien Roy  * CDDL HEADER END
20*2b24ab6bSSebastien Roy  */
21*2b24ab6bSSebastien Roy /*
22*2b24ab6bSSebastien Roy  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*2b24ab6bSSebastien Roy  * Use is subject to license terms.
24*2b24ab6bSSebastien Roy  */
25*2b24ab6bSSebastien Roy 
26*2b24ab6bSSebastien Roy #include <assert.h>
27*2b24ab6bSSebastien Roy #include <stdio.h>
28*2b24ab6bSSebastien Roy #include <errno.h>
29*2b24ab6bSSebastien Roy #include <stdlib.h>
30*2b24ab6bSSebastien Roy #include <unistd.h>
31*2b24ab6bSSebastien Roy #include <sys/types.h>
32*2b24ab6bSSebastien Roy #include <fcntl.h>
33*2b24ab6bSSebastien Roy #include <stropts.h>
34*2b24ab6bSSebastien Roy #include <string.h>
35*2b24ab6bSSebastien Roy #include <netdb.h>
36*2b24ab6bSSebastien Roy #include <sys/conf.h>
37*2b24ab6bSSebastien Roy #include <sys/socket.h>
38*2b24ab6bSSebastien Roy #include <netinet/in.h>
39*2b24ab6bSSebastien Roy #include <inet/iptun.h>
40*2b24ab6bSSebastien Roy #include <sys/dls.h>
41*2b24ab6bSSebastien Roy #include <libdlpi.h>
42*2b24ab6bSSebastien Roy #include <libdladm_impl.h>
43*2b24ab6bSSebastien Roy #include <libdllink.h>
44*2b24ab6bSSebastien Roy #include <libdliptun.h>
45*2b24ab6bSSebastien Roy 
46*2b24ab6bSSebastien Roy /*
47*2b24ab6bSSebastien Roy  * IP Tunneling Administration Library.
48*2b24ab6bSSebastien Roy  * This library is used by dladm(1M) and to configure IP tunnel links.
49*2b24ab6bSSebastien Roy  */
50*2b24ab6bSSebastien Roy 
51*2b24ab6bSSebastien Roy #define	IPTUN_CONF_TYPE		"type"
52*2b24ab6bSSebastien Roy #define	IPTUN_CONF_LADDR	"laddr"
53*2b24ab6bSSebastien Roy #define	IPTUN_CONF_RADDR	"raddr"
54*2b24ab6bSSebastien Roy 
55*2b24ab6bSSebastien Roy /*
56*2b24ab6bSSebastien Roy  * If IPTUN_CREATE and IPTUN_MODIFY include IPsec policy and IPsec hasn't
57*2b24ab6bSSebastien Roy  * loaded yet, the ioctls may return EAGAIN.  We try the ioctl
58*2b24ab6bSSebastien Roy  * IPTUN_IOCTL_ATTEMPT_LIMIT times and wait IPTUN_IOCTL_ATTEMPT_INTERVAL
59*2b24ab6bSSebastien Roy  * microseconds between attempts.
60*2b24ab6bSSebastien Roy  */
61*2b24ab6bSSebastien Roy #define	IPTUN_IOCTL_ATTEMPT_LIMIT	3
62*2b24ab6bSSebastien Roy #define	IPTUN_IOCTL_ATTEMPT_INTERVAL	10000
63*2b24ab6bSSebastien Roy 
64*2b24ab6bSSebastien Roy dladm_status_t
65*2b24ab6bSSebastien Roy i_iptun_ioctl(dladm_handle_t handle, int cmd, void *dp)
66*2b24ab6bSSebastien Roy {
67*2b24ab6bSSebastien Roy 	dladm_status_t	status = DLADM_STATUS_OK;
68*2b24ab6bSSebastien Roy 	uint_t		attempt;
69*2b24ab6bSSebastien Roy 
70*2b24ab6bSSebastien Roy 	for (attempt = 0; attempt < IPTUN_IOCTL_ATTEMPT_LIMIT; attempt++) {
71*2b24ab6bSSebastien Roy 		if (attempt != 0)
72*2b24ab6bSSebastien Roy 			(void) usleep(IPTUN_IOCTL_ATTEMPT_INTERVAL);
73*2b24ab6bSSebastien Roy 		status = (ioctl(dladm_dld_fd(handle), cmd, dp) == 0) ?
74*2b24ab6bSSebastien Roy 		    DLADM_STATUS_OK : dladm_errno2status(errno);
75*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_TRYAGAIN)
76*2b24ab6bSSebastien Roy 			break;
77*2b24ab6bSSebastien Roy 	}
78*2b24ab6bSSebastien Roy 	return (status);
79*2b24ab6bSSebastien Roy }
80*2b24ab6bSSebastien Roy 
81*2b24ab6bSSebastien Roy /*
82*2b24ab6bSSebastien Roy  * Given tunnel paramaters as supplied by a library consumer, fill in kernel
83*2b24ab6bSSebastien Roy  * parameters to be passed down to the iptun control device.
84*2b24ab6bSSebastien Roy  */
85*2b24ab6bSSebastien Roy static dladm_status_t
86*2b24ab6bSSebastien Roy i_iptun_kparams(dladm_handle_t handle, const iptun_params_t *params,
87*2b24ab6bSSebastien Roy     iptun_kparams_t *ik)
88*2b24ab6bSSebastien Roy {
89*2b24ab6bSSebastien Roy 	dladm_status_t	status;
90*2b24ab6bSSebastien Roy 	struct addrinfo	*ai, hints;
91*2b24ab6bSSebastien Roy 	iptun_kparams_t	tmpik;
92*2b24ab6bSSebastien Roy 	iptun_type_t	iptuntype = IPTUN_TYPE_UNKNOWN;
93*2b24ab6bSSebastien Roy 
94*2b24ab6bSSebastien Roy 	(void) memset(ik, 0, sizeof (*ik));
95*2b24ab6bSSebastien Roy 
96*2b24ab6bSSebastien Roy 	ik->iptun_kparam_linkid = params->iptun_param_linkid;
97*2b24ab6bSSebastien Roy 
98*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_TYPE) {
99*2b24ab6bSSebastien Roy 		ik->iptun_kparam_type = iptuntype = params->iptun_param_type;
100*2b24ab6bSSebastien Roy 		ik->iptun_kparam_flags |= IPTUN_KPARAM_TYPE;
101*2b24ab6bSSebastien Roy 	}
102*2b24ab6bSSebastien Roy 
103*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)) {
104*2b24ab6bSSebastien Roy 		if (iptuntype == IPTUN_TYPE_UNKNOWN) {
105*2b24ab6bSSebastien Roy 			/*
106*2b24ab6bSSebastien Roy 			 * We need to get the type of this existing tunnel in
107*2b24ab6bSSebastien Roy 			 * order to validate and/or look up the right kind of
108*2b24ab6bSSebastien Roy 			 * IP address.
109*2b24ab6bSSebastien Roy 			 */
110*2b24ab6bSSebastien Roy 			tmpik.iptun_kparam_linkid = params->iptun_param_linkid;
111*2b24ab6bSSebastien Roy 			status = i_iptun_ioctl(handle, IPTUN_INFO, &tmpik);
112*2b24ab6bSSebastien Roy 			if (status != DLADM_STATUS_OK)
113*2b24ab6bSSebastien Roy 				return (status);
114*2b24ab6bSSebastien Roy 			iptuntype = tmpik.iptun_kparam_type;
115*2b24ab6bSSebastien Roy 		}
116*2b24ab6bSSebastien Roy 
117*2b24ab6bSSebastien Roy 		(void) memset(&hints, 0, sizeof (hints));
118*2b24ab6bSSebastien Roy 		switch (iptuntype) {
119*2b24ab6bSSebastien Roy 		case IPTUN_TYPE_IPV4:
120*2b24ab6bSSebastien Roy 		case IPTUN_TYPE_6TO4:
121*2b24ab6bSSebastien Roy 			hints.ai_family = AF_INET;
122*2b24ab6bSSebastien Roy 			break;
123*2b24ab6bSSebastien Roy 		case IPTUN_TYPE_IPV6:
124*2b24ab6bSSebastien Roy 			hints.ai_family = AF_INET6;
125*2b24ab6bSSebastien Roy 			break;
126*2b24ab6bSSebastien Roy 		}
127*2b24ab6bSSebastien Roy 	}
128*2b24ab6bSSebastien Roy 
129*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_LADDR) {
130*2b24ab6bSSebastien Roy 		if (getaddrinfo(params->iptun_param_laddr, NULL, &hints, &ai) !=
131*2b24ab6bSSebastien Roy 		    0)
132*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNLADDR);
133*2b24ab6bSSebastien Roy 		if (ai->ai_next != NULL) {
134*2b24ab6bSSebastien Roy 			freeaddrinfo(ai);
135*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNLADDR);
136*2b24ab6bSSebastien Roy 		}
137*2b24ab6bSSebastien Roy 		(void) memcpy(&ik->iptun_kparam_laddr, ai->ai_addr,
138*2b24ab6bSSebastien Roy 		    ai->ai_addrlen);
139*2b24ab6bSSebastien Roy 		ik->iptun_kparam_flags |= IPTUN_KPARAM_LADDR;
140*2b24ab6bSSebastien Roy 		freeaddrinfo(ai);
141*2b24ab6bSSebastien Roy 	}
142*2b24ab6bSSebastien Roy 
143*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_RADDR) {
144*2b24ab6bSSebastien Roy 		if (getaddrinfo(params->iptun_param_raddr, NULL, &hints, &ai) !=
145*2b24ab6bSSebastien Roy 		    0)
146*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNRADDR);
147*2b24ab6bSSebastien Roy 		if (ai->ai_next != NULL) {
148*2b24ab6bSSebastien Roy 			freeaddrinfo(ai);
149*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNRADDR);
150*2b24ab6bSSebastien Roy 		}
151*2b24ab6bSSebastien Roy 		(void) memcpy(&ik->iptun_kparam_raddr, ai->ai_addr,
152*2b24ab6bSSebastien Roy 		    ai->ai_addrlen);
153*2b24ab6bSSebastien Roy 		ik->iptun_kparam_flags |= IPTUN_KPARAM_RADDR;
154*2b24ab6bSSebastien Roy 		freeaddrinfo(ai);
155*2b24ab6bSSebastien Roy 	}
156*2b24ab6bSSebastien Roy 
157*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_SECINFO) {
158*2b24ab6bSSebastien Roy 		ik->iptun_kparam_secinfo = params->iptun_param_secinfo;
159*2b24ab6bSSebastien Roy 		ik->iptun_kparam_flags |= IPTUN_KPARAM_SECINFO;
160*2b24ab6bSSebastien Roy 	}
161*2b24ab6bSSebastien Roy 
162*2b24ab6bSSebastien Roy 	return (DLADM_STATUS_OK);
163*2b24ab6bSSebastien Roy }
164*2b24ab6bSSebastien Roy 
165*2b24ab6bSSebastien Roy /*
166*2b24ab6bSSebastien Roy  * The inverse of i_iptun_kparams().  Given kernel tunnel paramaters as
167*2b24ab6bSSebastien Roy  * returned from an IPTUN_INFO ioctl, fill in tunnel parameters.
168*2b24ab6bSSebastien Roy  */
169*2b24ab6bSSebastien Roy static dladm_status_t
170*2b24ab6bSSebastien Roy i_iptun_params(const iptun_kparams_t *ik, iptun_params_t *params)
171*2b24ab6bSSebastien Roy {
172*2b24ab6bSSebastien Roy 	socklen_t salen;
173*2b24ab6bSSebastien Roy 
174*2b24ab6bSSebastien Roy 	(void) memset(params, 0, sizeof (*params));
175*2b24ab6bSSebastien Roy 
176*2b24ab6bSSebastien Roy 	params->iptun_param_linkid = ik->iptun_kparam_linkid;
177*2b24ab6bSSebastien Roy 
178*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_TYPE) {
179*2b24ab6bSSebastien Roy 		params->iptun_param_type = ik->iptun_kparam_type;
180*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_TYPE;
181*2b24ab6bSSebastien Roy 	}
182*2b24ab6bSSebastien Roy 
183*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_LADDR) {
184*2b24ab6bSSebastien Roy 		salen = ik->iptun_kparam_laddr.ss_family == AF_INET ?
185*2b24ab6bSSebastien Roy 		    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
186*2b24ab6bSSebastien Roy 		if (getnameinfo((const struct sockaddr *)
187*2b24ab6bSSebastien Roy 		    &ik->iptun_kparam_laddr, salen, params->iptun_param_laddr,
188*2b24ab6bSSebastien Roy 		    sizeof (params->iptun_param_laddr), NULL, 0,
189*2b24ab6bSSebastien Roy 		    NI_NUMERICHOST) != 0) {
190*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNLADDR);
191*2b24ab6bSSebastien Roy 		}
192*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_LADDR;
193*2b24ab6bSSebastien Roy 	}
194*2b24ab6bSSebastien Roy 
195*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_RADDR) {
196*2b24ab6bSSebastien Roy 		salen = ik->iptun_kparam_raddr.ss_family == AF_INET ?
197*2b24ab6bSSebastien Roy 		    sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
198*2b24ab6bSSebastien Roy 		if (getnameinfo((const struct sockaddr *)
199*2b24ab6bSSebastien Roy 		    &ik->iptun_kparam_raddr, salen, params->iptun_param_raddr,
200*2b24ab6bSSebastien Roy 		    sizeof (params->iptun_param_raddr), NULL, 0,
201*2b24ab6bSSebastien Roy 		    NI_NUMERICHOST) != 0) {
202*2b24ab6bSSebastien Roy 			return (DLADM_STATUS_BADIPTUNRADDR);
203*2b24ab6bSSebastien Roy 		}
204*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_RADDR;
205*2b24ab6bSSebastien Roy 	}
206*2b24ab6bSSebastien Roy 
207*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_SECINFO) {
208*2b24ab6bSSebastien Roy 		params->iptun_param_secinfo = ik->iptun_kparam_secinfo;
209*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_SECINFO;
210*2b24ab6bSSebastien Roy 	}
211*2b24ab6bSSebastien Roy 
212*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_IMPLICIT)
213*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_IMPLICIT;
214*2b24ab6bSSebastien Roy 
215*2b24ab6bSSebastien Roy 	if (ik->iptun_kparam_flags & IPTUN_KPARAM_IPSECPOL)
216*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_IPSECPOL;
217*2b24ab6bSSebastien Roy 
218*2b24ab6bSSebastien Roy 	return (DLADM_STATUS_OK);
219*2b24ab6bSSebastien Roy }
220*2b24ab6bSSebastien Roy 
221*2b24ab6bSSebastien Roy dladm_status_t
222*2b24ab6bSSebastien Roy i_iptun_get_sysparams(dladm_handle_t handle, iptun_params_t *params)
223*2b24ab6bSSebastien Roy {
224*2b24ab6bSSebastien Roy 	dladm_status_t	status = DLADM_STATUS_OK;
225*2b24ab6bSSebastien Roy 	iptun_kparams_t	ik;
226*2b24ab6bSSebastien Roy 
227*2b24ab6bSSebastien Roy 	ik.iptun_kparam_linkid = params->iptun_param_linkid;
228*2b24ab6bSSebastien Roy 	status = i_iptun_ioctl(handle, IPTUN_INFO, &ik);
229*2b24ab6bSSebastien Roy 	if (status == DLADM_STATUS_OK)
230*2b24ab6bSSebastien Roy 		status = i_iptun_params(&ik, params);
231*2b24ab6bSSebastien Roy 	return (status);
232*2b24ab6bSSebastien Roy }
233*2b24ab6bSSebastien Roy 
234*2b24ab6bSSebastien Roy /*
235*2b24ab6bSSebastien Roy  * Read tunnel parameters from persistent storage.  Note that the tunnel type
236*2b24ab6bSSebastien Roy  * is the only thing which must always be in the configuratioh.  All other
237*2b24ab6bSSebastien Roy  * parameters (currently the source and destination addresses) may or may not
238*2b24ab6bSSebastien Roy  * have been configured, and therefore may not have been set.
239*2b24ab6bSSebastien Roy  */
240*2b24ab6bSSebastien Roy static dladm_status_t
241*2b24ab6bSSebastien Roy i_iptun_get_dbparams(dladm_handle_t handle, iptun_params_t *params)
242*2b24ab6bSSebastien Roy {
243*2b24ab6bSSebastien Roy 	dladm_status_t		status;
244*2b24ab6bSSebastien Roy 	dladm_conf_t		conf;
245*2b24ab6bSSebastien Roy 	datalink_class_t	class;
246*2b24ab6bSSebastien Roy 	uint64_t		temp;
247*2b24ab6bSSebastien Roy 
248*2b24ab6bSSebastien Roy 	/* First, make sure that this is an IP tunnel. */
249*2b24ab6bSSebastien Roy 	if ((status = dladm_datalink_id2info(handle, params->iptun_param_linkid,
250*2b24ab6bSSebastien Roy 	    NULL, &class, NULL, NULL, 0)) != DLADM_STATUS_OK)
251*2b24ab6bSSebastien Roy 		return (status);
252*2b24ab6bSSebastien Roy 	if (class != DATALINK_CLASS_IPTUN)
253*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_LINKINVAL);
254*2b24ab6bSSebastien Roy 
255*2b24ab6bSSebastien Roy 	status = dladm_read_conf(handle, params->iptun_param_linkid, &conf);
256*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
257*2b24ab6bSSebastien Roy 		return (status);
258*2b24ab6bSSebastien Roy 
259*2b24ab6bSSebastien Roy 	params->iptun_param_flags = 0;
260*2b24ab6bSSebastien Roy 
261*2b24ab6bSSebastien Roy 	if ((status = dladm_get_conf_field(handle, conf, IPTUN_CONF_TYPE, &temp,
262*2b24ab6bSSebastien Roy 	    sizeof (temp))) != DLADM_STATUS_OK)
263*2b24ab6bSSebastien Roy 		goto done;
264*2b24ab6bSSebastien Roy 	params->iptun_param_type = (iptun_type_t)temp;
265*2b24ab6bSSebastien Roy 	params->iptun_param_flags |= IPTUN_PARAM_TYPE;
266*2b24ab6bSSebastien Roy 
267*2b24ab6bSSebastien Roy 	if (dladm_get_conf_field(handle, conf, IPTUN_CONF_LADDR,
268*2b24ab6bSSebastien Roy 	    params->iptun_param_laddr, sizeof (params->iptun_param_laddr)) ==
269*2b24ab6bSSebastien Roy 	    DLADM_STATUS_OK)
270*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_LADDR;
271*2b24ab6bSSebastien Roy 
272*2b24ab6bSSebastien Roy 	if (dladm_get_conf_field(handle, conf, IPTUN_CONF_RADDR,
273*2b24ab6bSSebastien Roy 	    params->iptun_param_raddr, sizeof (params->iptun_param_raddr)) ==
274*2b24ab6bSSebastien Roy 	    DLADM_STATUS_OK)
275*2b24ab6bSSebastien Roy 		params->iptun_param_flags |= IPTUN_PARAM_RADDR;
276*2b24ab6bSSebastien Roy 
277*2b24ab6bSSebastien Roy done:
278*2b24ab6bSSebastien Roy 	dladm_destroy_conf(handle, conf);
279*2b24ab6bSSebastien Roy 	return (status);
280*2b24ab6bSSebastien Roy }
281*2b24ab6bSSebastien Roy 
282*2b24ab6bSSebastien Roy static dladm_status_t
283*2b24ab6bSSebastien Roy i_iptun_create_sys(dladm_handle_t handle, iptun_params_t *params)
284*2b24ab6bSSebastien Roy {
285*2b24ab6bSSebastien Roy 	iptun_kparams_t	ik;
286*2b24ab6bSSebastien Roy 	dladm_status_t	status = DLADM_STATUS_OK;
287*2b24ab6bSSebastien Roy 
288*2b24ab6bSSebastien Roy 	/* The tunnel type is required for creation. */
289*2b24ab6bSSebastien Roy 	if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE))
290*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_IPTUNTYPEREQD);
291*2b24ab6bSSebastien Roy 
292*2b24ab6bSSebastien Roy 	if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK)
293*2b24ab6bSSebastien Roy 		status = i_iptun_ioctl(handle, IPTUN_CREATE, &ik);
294*2b24ab6bSSebastien Roy 	return (status);
295*2b24ab6bSSebastien Roy }
296*2b24ab6bSSebastien Roy 
297*2b24ab6bSSebastien Roy static dladm_status_t
298*2b24ab6bSSebastien Roy i_iptun_create_db(dladm_handle_t handle, const char *name,
299*2b24ab6bSSebastien Roy     iptun_params_t *params, uint32_t media)
300*2b24ab6bSSebastien Roy {
301*2b24ab6bSSebastien Roy 	dladm_conf_t	conf;
302*2b24ab6bSSebastien Roy 	dladm_status_t	status;
303*2b24ab6bSSebastien Roy 	uint64_t	storage;
304*2b24ab6bSSebastien Roy 
305*2b24ab6bSSebastien Roy 	status = dladm_create_conf(handle, name, params->iptun_param_linkid,
306*2b24ab6bSSebastien Roy 	    DATALINK_CLASS_IPTUN, media, &conf);
307*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
308*2b24ab6bSSebastien Roy 		return (status);
309*2b24ab6bSSebastien Roy 
310*2b24ab6bSSebastien Roy 	assert(params->iptun_param_flags & IPTUN_PARAM_TYPE);
311*2b24ab6bSSebastien Roy 	storage = params->iptun_param_type;
312*2b24ab6bSSebastien Roy 	status = dladm_set_conf_field(handle, conf, IPTUN_CONF_TYPE,
313*2b24ab6bSSebastien Roy 	    DLADM_TYPE_UINT64, &storage);
314*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
315*2b24ab6bSSebastien Roy 		goto done;
316*2b24ab6bSSebastien Roy 
317*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_LADDR) {
318*2b24ab6bSSebastien Roy 		status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR,
319*2b24ab6bSSebastien Roy 		    DLADM_TYPE_STR, params->iptun_param_laddr);
320*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
321*2b24ab6bSSebastien Roy 			goto done;
322*2b24ab6bSSebastien Roy 	}
323*2b24ab6bSSebastien Roy 
324*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_RADDR) {
325*2b24ab6bSSebastien Roy 		status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR,
326*2b24ab6bSSebastien Roy 		    DLADM_TYPE_STR, params->iptun_param_raddr);
327*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
328*2b24ab6bSSebastien Roy 			goto done;
329*2b24ab6bSSebastien Roy 	}
330*2b24ab6bSSebastien Roy 
331*2b24ab6bSSebastien Roy 	status = dladm_write_conf(handle, conf);
332*2b24ab6bSSebastien Roy 
333*2b24ab6bSSebastien Roy done:
334*2b24ab6bSSebastien Roy 	dladm_destroy_conf(handle, conf);
335*2b24ab6bSSebastien Roy 	return (status);
336*2b24ab6bSSebastien Roy }
337*2b24ab6bSSebastien Roy 
338*2b24ab6bSSebastien Roy static dladm_status_t
339*2b24ab6bSSebastien Roy i_iptun_delete_sys(dladm_handle_t handle, datalink_id_t linkid)
340*2b24ab6bSSebastien Roy {
341*2b24ab6bSSebastien Roy 	dladm_status_t status;
342*2b24ab6bSSebastien Roy 
343*2b24ab6bSSebastien Roy 	status = i_iptun_ioctl(handle, IPTUN_DELETE, &linkid);
344*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
345*2b24ab6bSSebastien Roy 		return (status);
346*2b24ab6bSSebastien Roy 	(void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_ACTIVE);
347*2b24ab6bSSebastien Roy 	return (DLADM_STATUS_OK);
348*2b24ab6bSSebastien Roy }
349*2b24ab6bSSebastien Roy 
350*2b24ab6bSSebastien Roy static dladm_status_t
351*2b24ab6bSSebastien Roy i_iptun_modify_sys(dladm_handle_t handle, const iptun_params_t *params)
352*2b24ab6bSSebastien Roy {
353*2b24ab6bSSebastien Roy 	iptun_kparams_t	ik;
354*2b24ab6bSSebastien Roy 	dladm_status_t	status;
355*2b24ab6bSSebastien Roy 
356*2b24ab6bSSebastien Roy 	if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK)
357*2b24ab6bSSebastien Roy 		status = i_iptun_ioctl(handle, IPTUN_MODIFY, &ik);
358*2b24ab6bSSebastien Roy 	return (status);
359*2b24ab6bSSebastien Roy }
360*2b24ab6bSSebastien Roy 
361*2b24ab6bSSebastien Roy static dladm_status_t
362*2b24ab6bSSebastien Roy i_iptun_modify_db(dladm_handle_t handle, const iptun_params_t *params)
363*2b24ab6bSSebastien Roy {
364*2b24ab6bSSebastien Roy 	dladm_conf_t	conf;
365*2b24ab6bSSebastien Roy 	dladm_status_t	status;
366*2b24ab6bSSebastien Roy 
367*2b24ab6bSSebastien Roy 	assert(params->iptun_param_flags &
368*2b24ab6bSSebastien Roy 	    (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR));
369*2b24ab6bSSebastien Roy 
370*2b24ab6bSSebastien Roy 	/*
371*2b24ab6bSSebastien Roy 	 * The only parameters that can be modified persistently are the local
372*2b24ab6bSSebastien Roy 	 * and remote addresses.
373*2b24ab6bSSebastien Roy 	 */
374*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & ~(IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR))
375*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_BADARG);
376*2b24ab6bSSebastien Roy 
377*2b24ab6bSSebastien Roy 	status = dladm_read_conf(handle, params->iptun_param_linkid, &conf);
378*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
379*2b24ab6bSSebastien Roy 		return (status);
380*2b24ab6bSSebastien Roy 
381*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_LADDR) {
382*2b24ab6bSSebastien Roy 		status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR,
383*2b24ab6bSSebastien Roy 		    DLADM_TYPE_STR, (void *)params->iptun_param_laddr);
384*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
385*2b24ab6bSSebastien Roy 			goto done;
386*2b24ab6bSSebastien Roy 	}
387*2b24ab6bSSebastien Roy 
388*2b24ab6bSSebastien Roy 	if (params->iptun_param_flags & IPTUN_PARAM_RADDR) {
389*2b24ab6bSSebastien Roy 		status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR,
390*2b24ab6bSSebastien Roy 		    DLADM_TYPE_STR, (void *)params->iptun_param_raddr);
391*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
392*2b24ab6bSSebastien Roy 			goto done;
393*2b24ab6bSSebastien Roy 	}
394*2b24ab6bSSebastien Roy 
395*2b24ab6bSSebastien Roy 	status = dladm_write_conf(handle, conf);
396*2b24ab6bSSebastien Roy 
397*2b24ab6bSSebastien Roy done:
398*2b24ab6bSSebastien Roy 	dladm_destroy_conf(handle, conf);
399*2b24ab6bSSebastien Roy 	return (status);
400*2b24ab6bSSebastien Roy }
401*2b24ab6bSSebastien Roy 
402*2b24ab6bSSebastien Roy dladm_status_t
403*2b24ab6bSSebastien Roy dladm_iptun_create(dladm_handle_t handle, const char *name,
404*2b24ab6bSSebastien Roy     iptun_params_t *params, uint32_t flags)
405*2b24ab6bSSebastien Roy {
406*2b24ab6bSSebastien Roy 	dladm_status_t	status;
407*2b24ab6bSSebastien Roy 	uint32_t	linkmgmt_flags = flags;
408*2b24ab6bSSebastien Roy 	uint32_t	media;
409*2b24ab6bSSebastien Roy 
410*2b24ab6bSSebastien Roy 	if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE))
411*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_IPTUNTYPEREQD);
412*2b24ab6bSSebastien Roy 
413*2b24ab6bSSebastien Roy 	switch (params->iptun_param_type) {
414*2b24ab6bSSebastien Roy 	case IPTUN_TYPE_IPV4:
415*2b24ab6bSSebastien Roy 		media = DL_IPV4;
416*2b24ab6bSSebastien Roy 		break;
417*2b24ab6bSSebastien Roy 	case IPTUN_TYPE_IPV6:
418*2b24ab6bSSebastien Roy 		media = DL_IPV6;
419*2b24ab6bSSebastien Roy 		break;
420*2b24ab6bSSebastien Roy 	case IPTUN_TYPE_6TO4:
421*2b24ab6bSSebastien Roy 		media = DL_6TO4;
422*2b24ab6bSSebastien Roy 		break;
423*2b24ab6bSSebastien Roy 	default:
424*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_IPTUNTYPE);
425*2b24ab6bSSebastien Roy 	}
426*2b24ab6bSSebastien Roy 
427*2b24ab6bSSebastien Roy 	status = dladm_create_datalink_id(handle, name, DATALINK_CLASS_IPTUN,
428*2b24ab6bSSebastien Roy 	    media, linkmgmt_flags, &params->iptun_param_linkid);
429*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
430*2b24ab6bSSebastien Roy 		return (status);
431*2b24ab6bSSebastien Roy 
432*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_PERSIST) {
433*2b24ab6bSSebastien Roy 		status = i_iptun_create_db(handle, name, params, media);
434*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
435*2b24ab6bSSebastien Roy 			goto done;
436*2b24ab6bSSebastien Roy 	}
437*2b24ab6bSSebastien Roy 
438*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_ACTIVE) {
439*2b24ab6bSSebastien Roy 		status = i_iptun_create_sys(handle, params);
440*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) {
441*2b24ab6bSSebastien Roy 			(void) dladm_remove_conf(handle,
442*2b24ab6bSSebastien Roy 			    params->iptun_param_linkid);
443*2b24ab6bSSebastien Roy 		}
444*2b24ab6bSSebastien Roy 	}
445*2b24ab6bSSebastien Roy 
446*2b24ab6bSSebastien Roy done:
447*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK) {
448*2b24ab6bSSebastien Roy 		(void) dladm_destroy_datalink_id(handle,
449*2b24ab6bSSebastien Roy 		    params->iptun_param_linkid, flags);
450*2b24ab6bSSebastien Roy 	}
451*2b24ab6bSSebastien Roy 	return (status);
452*2b24ab6bSSebastien Roy }
453*2b24ab6bSSebastien Roy 
454*2b24ab6bSSebastien Roy dladm_status_t
455*2b24ab6bSSebastien Roy dladm_iptun_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags)
456*2b24ab6bSSebastien Roy {
457*2b24ab6bSSebastien Roy 	dladm_status_t		status;
458*2b24ab6bSSebastien Roy 	datalink_class_t	class;
459*2b24ab6bSSebastien Roy 
460*2b24ab6bSSebastien Roy 	/* First, make sure that this is an IP tunnel. */
461*2b24ab6bSSebastien Roy 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
462*2b24ab6bSSebastien Roy 	    NULL, 0)) != DLADM_STATUS_OK)
463*2b24ab6bSSebastien Roy 		return (status);
464*2b24ab6bSSebastien Roy 	if (class != DATALINK_CLASS_IPTUN)
465*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_LINKINVAL);
466*2b24ab6bSSebastien Roy 
467*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_ACTIVE) {
468*2b24ab6bSSebastien Roy 		/*
469*2b24ab6bSSebastien Roy 		 * Note that if i_iptun_delete_sys() fails with
470*2b24ab6bSSebastien Roy 		 * DLADM_STATUS_NOTFOUND and the caller also wishes to delete
471*2b24ab6bSSebastien Roy 		 * the persistent configuration, we still fall through to the
472*2b24ab6bSSebastien Roy 		 * DLADM_OPT_PERSIST case in case the tunnel only exists
473*2b24ab6bSSebastien Roy 		 * persistently.
474*2b24ab6bSSebastien Roy 		 */
475*2b24ab6bSSebastien Roy 		status = i_iptun_delete_sys(handle, linkid);
476*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK &&
477*2b24ab6bSSebastien Roy 		    (status != DLADM_STATUS_NOTFOUND ||
478*2b24ab6bSSebastien Roy 		    !(flags & DLADM_OPT_PERSIST)))
479*2b24ab6bSSebastien Roy 			return (status);
480*2b24ab6bSSebastien Roy 	}
481*2b24ab6bSSebastien Roy 
482*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_PERSIST) {
483*2b24ab6bSSebastien Roy 		(void) dladm_remove_conf(handle, linkid);
484*2b24ab6bSSebastien Roy 		(void) dladm_destroy_datalink_id(handle, linkid,
485*2b24ab6bSSebastien Roy 		    DLADM_OPT_PERSIST);
486*2b24ab6bSSebastien Roy 	}
487*2b24ab6bSSebastien Roy 	return (DLADM_STATUS_OK);
488*2b24ab6bSSebastien Roy }
489*2b24ab6bSSebastien Roy 
490*2b24ab6bSSebastien Roy dladm_status_t
491*2b24ab6bSSebastien Roy dladm_iptun_modify(dladm_handle_t handle, const iptun_params_t *params,
492*2b24ab6bSSebastien Roy     uint32_t flags)
493*2b24ab6bSSebastien Roy {
494*2b24ab6bSSebastien Roy 	dladm_status_t	status = DLADM_STATUS_OK;
495*2b24ab6bSSebastien Roy 	iptun_params_t	old_params;
496*2b24ab6bSSebastien Roy 
497*2b24ab6bSSebastien Roy 	/*
498*2b24ab6bSSebastien Roy 	 * We can only modify the tunnel source, tunnel destination, or IPsec
499*2b24ab6bSSebastien Roy 	 * policy.
500*2b24ab6bSSebastien Roy 	 */
501*2b24ab6bSSebastien Roy 	if (!(params->iptun_param_flags &
502*2b24ab6bSSebastien Roy 	    (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR|IPTUN_PARAM_SECINFO)))
503*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_BADARG);
504*2b24ab6bSSebastien Roy 
505*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_PERSIST) {
506*2b24ab6bSSebastien Roy 		/*
507*2b24ab6bSSebastien Roy 		 * Before we change the database, save the old configuration
508*2b24ab6bSSebastien Roy 		 * so that we can revert back if an error occurs.
509*2b24ab6bSSebastien Roy 		 */
510*2b24ab6bSSebastien Roy 		old_params.iptun_param_linkid = params->iptun_param_linkid;
511*2b24ab6bSSebastien Roy 		status = i_iptun_get_dbparams(handle, &old_params);
512*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
513*2b24ab6bSSebastien Roy 			return (status);
514*2b24ab6bSSebastien Roy 		/* we'll only need to revert the parameters being modified */
515*2b24ab6bSSebastien Roy 		old_params.iptun_param_flags = params->iptun_param_flags;
516*2b24ab6bSSebastien Roy 
517*2b24ab6bSSebastien Roy 		status = i_iptun_modify_db(handle, params);
518*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK)
519*2b24ab6bSSebastien Roy 			return (status);
520*2b24ab6bSSebastien Roy 	}
521*2b24ab6bSSebastien Roy 
522*2b24ab6bSSebastien Roy 	if (flags & DLADM_OPT_ACTIVE) {
523*2b24ab6bSSebastien Roy 		status = i_iptun_modify_sys(handle, params);
524*2b24ab6bSSebastien Roy 		if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) {
525*2b24ab6bSSebastien Roy 			(void) i_iptun_modify_db(handle, &old_params);
526*2b24ab6bSSebastien Roy 		}
527*2b24ab6bSSebastien Roy 	}
528*2b24ab6bSSebastien Roy 
529*2b24ab6bSSebastien Roy 	return (status);
530*2b24ab6bSSebastien Roy }
531*2b24ab6bSSebastien Roy 
532*2b24ab6bSSebastien Roy dladm_status_t
533*2b24ab6bSSebastien Roy dladm_iptun_getparams(dladm_handle_t handle, iptun_params_t *params,
534*2b24ab6bSSebastien Roy     uint32_t flags)
535*2b24ab6bSSebastien Roy {
536*2b24ab6bSSebastien Roy 	if (flags == DLADM_OPT_ACTIVE)
537*2b24ab6bSSebastien Roy 		return (i_iptun_get_sysparams(handle, params));
538*2b24ab6bSSebastien Roy 	else if (flags == DLADM_OPT_PERSIST)
539*2b24ab6bSSebastien Roy 		return (i_iptun_get_dbparams(handle, params));
540*2b24ab6bSSebastien Roy 	else
541*2b24ab6bSSebastien Roy 		return (DLADM_STATUS_BADARG);
542*2b24ab6bSSebastien Roy }
543*2b24ab6bSSebastien Roy 
544*2b24ab6bSSebastien Roy static int
545*2b24ab6bSSebastien Roy i_iptun_up(dladm_handle_t handle, datalink_id_t linkid, void *arg)
546*2b24ab6bSSebastien Roy {
547*2b24ab6bSSebastien Roy 	dladm_status_t	*statusp = arg;
548*2b24ab6bSSebastien Roy 	dladm_status_t	status;
549*2b24ab6bSSebastien Roy 	iptun_params_t	params;
550*2b24ab6bSSebastien Roy 	boolean_t	id_up = B_FALSE;
551*2b24ab6bSSebastien Roy 
552*2b24ab6bSSebastien Roy 	status = dladm_up_datalink_id(handle, linkid);
553*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK)
554*2b24ab6bSSebastien Roy 		goto done;
555*2b24ab6bSSebastien Roy 	id_up = B_TRUE;
556*2b24ab6bSSebastien Roy 
557*2b24ab6bSSebastien Roy 	(void) memset(&params, 0, sizeof (params));
558*2b24ab6bSSebastien Roy 
559*2b24ab6bSSebastien Roy 	params.iptun_param_linkid = linkid;
560*2b24ab6bSSebastien Roy 	if ((status = i_iptun_get_dbparams(handle, &params)) == DLADM_STATUS_OK)
561*2b24ab6bSSebastien Roy 		status = i_iptun_create_sys(handle, &params);
562*2b24ab6bSSebastien Roy done:
563*2b24ab6bSSebastien Roy 	if (statusp != NULL)
564*2b24ab6bSSebastien Roy 		*statusp = status;
565*2b24ab6bSSebastien Roy 	if (status != DLADM_STATUS_OK && id_up) {
566*2b24ab6bSSebastien Roy 		(void) dladm_destroy_datalink_id(handle, linkid,
567*2b24ab6bSSebastien Roy 		    DLADM_OPT_ACTIVE);
568*2b24ab6bSSebastien Roy 	}
569*2b24ab6bSSebastien Roy 	return (DLADM_WALK_CONTINUE);
570*2b24ab6bSSebastien Roy }
571*2b24ab6bSSebastien Roy 
572*2b24ab6bSSebastien Roy static int
573*2b24ab6bSSebastien Roy i_iptun_down(dladm_handle_t handle, datalink_id_t linkid, void *arg)
574*2b24ab6bSSebastien Roy {
575*2b24ab6bSSebastien Roy 	dladm_status_t	*statusp = arg;
576*2b24ab6bSSebastien Roy 	dladm_status_t	status;
577*2b24ab6bSSebastien Roy 
578*2b24ab6bSSebastien Roy 	status = i_iptun_delete_sys(handle, linkid);
579*2b24ab6bSSebastien Roy 	if (statusp != NULL)
580*2b24ab6bSSebastien Roy 		*statusp = status;
581*2b24ab6bSSebastien Roy 	return (DLADM_WALK_CONTINUE);
582*2b24ab6bSSebastien Roy }
583*2b24ab6bSSebastien Roy 
584*2b24ab6bSSebastien Roy /* ARGSUSED */
585*2b24ab6bSSebastien Roy dladm_status_t
586*2b24ab6bSSebastien Roy dladm_iptun_up(dladm_handle_t handle, datalink_id_t linkid)
587*2b24ab6bSSebastien Roy {
588*2b24ab6bSSebastien Roy 	dladm_status_t status = DLADM_STATUS_OK;
589*2b24ab6bSSebastien Roy 
590*2b24ab6bSSebastien Roy 	if (linkid == DATALINK_ALL_LINKID) {
591*2b24ab6bSSebastien Roy 		(void) dladm_walk_datalink_id(i_iptun_up, handle, NULL,
592*2b24ab6bSSebastien Roy 		    DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE,
593*2b24ab6bSSebastien Roy 		    DLADM_OPT_PERSIST);
594*2b24ab6bSSebastien Roy 	} else {
595*2b24ab6bSSebastien Roy 		(void) i_iptun_up(handle, linkid, &status);
596*2b24ab6bSSebastien Roy 	}
597*2b24ab6bSSebastien Roy 	return (status);
598*2b24ab6bSSebastien Roy }
599*2b24ab6bSSebastien Roy 
600*2b24ab6bSSebastien Roy dladm_status_t
601*2b24ab6bSSebastien Roy dladm_iptun_down(dladm_handle_t handle, datalink_id_t linkid)
602*2b24ab6bSSebastien Roy {
603*2b24ab6bSSebastien Roy 	dladm_status_t status = DLADM_STATUS_OK;
604*2b24ab6bSSebastien Roy 
605*2b24ab6bSSebastien Roy 	if (linkid == DATALINK_ALL_LINKID) {
606*2b24ab6bSSebastien Roy 		(void) dladm_walk_datalink_id(i_iptun_down, handle, NULL,
607*2b24ab6bSSebastien Roy 		    DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE,
608*2b24ab6bSSebastien Roy 		    DLADM_OPT_ACTIVE);
609*2b24ab6bSSebastien Roy 	} else {
610*2b24ab6bSSebastien Roy 		(void) i_iptun_down(handle, linkid, &status);
611*2b24ab6bSSebastien Roy 	}
612*2b24ab6bSSebastien Roy 	return (status);
613*2b24ab6bSSebastien Roy }
614*2b24ab6bSSebastien Roy 
615*2b24ab6bSSebastien Roy dladm_status_t
616*2b24ab6bSSebastien Roy dladm_iptun_set6to4relay(dladm_handle_t handle, struct in_addr *relay)
617*2b24ab6bSSebastien Roy {
618*2b24ab6bSSebastien Roy 	return (i_iptun_ioctl(handle, IPTUN_SET_6TO4RELAY, relay));
619*2b24ab6bSSebastien Roy }
620*2b24ab6bSSebastien Roy 
621*2b24ab6bSSebastien Roy dladm_status_t
622*2b24ab6bSSebastien Roy dladm_iptun_get6to4relay(dladm_handle_t handle, struct in_addr *relay)
623*2b24ab6bSSebastien Roy {
624*2b24ab6bSSebastien Roy 	return (i_iptun_ioctl(handle, IPTUN_GET_6TO4RELAY, relay));
625*2b24ab6bSSebastien Roy }
626