110616SSebastien.Roy@Sun.COM /* 210616SSebastien.Roy@Sun.COM * CDDL HEADER START 310616SSebastien.Roy@Sun.COM * 410616SSebastien.Roy@Sun.COM * The contents of this file are subject to the terms of the 510616SSebastien.Roy@Sun.COM * Common Development and Distribution License (the "License"). 610616SSebastien.Roy@Sun.COM * You may not use this file except in compliance with the License. 710616SSebastien.Roy@Sun.COM * 810616SSebastien.Roy@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 910616SSebastien.Roy@Sun.COM * or http://www.opensolaris.org/os/licensing. 1010616SSebastien.Roy@Sun.COM * See the License for the specific language governing permissions 1110616SSebastien.Roy@Sun.COM * and limitations under the License. 1210616SSebastien.Roy@Sun.COM * 1310616SSebastien.Roy@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 1410616SSebastien.Roy@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1510616SSebastien.Roy@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 1610616SSebastien.Roy@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 1710616SSebastien.Roy@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 1810616SSebastien.Roy@Sun.COM * 1910616SSebastien.Roy@Sun.COM * CDDL HEADER END 2010616SSebastien.Roy@Sun.COM */ 2110616SSebastien.Roy@Sun.COM /* 22*12824SCathy.Zhou@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2310616SSebastien.Roy@Sun.COM */ 2410616SSebastien.Roy@Sun.COM 2510616SSebastien.Roy@Sun.COM #include <assert.h> 2610616SSebastien.Roy@Sun.COM #include <stdio.h> 2710616SSebastien.Roy@Sun.COM #include <errno.h> 2810616SSebastien.Roy@Sun.COM #include <stdlib.h> 2910616SSebastien.Roy@Sun.COM #include <unistd.h> 3010616SSebastien.Roy@Sun.COM #include <sys/types.h> 3110616SSebastien.Roy@Sun.COM #include <fcntl.h> 3210616SSebastien.Roy@Sun.COM #include <stropts.h> 3310616SSebastien.Roy@Sun.COM #include <string.h> 3410616SSebastien.Roy@Sun.COM #include <netdb.h> 3510616SSebastien.Roy@Sun.COM #include <sys/conf.h> 3610616SSebastien.Roy@Sun.COM #include <sys/socket.h> 3710616SSebastien.Roy@Sun.COM #include <netinet/in.h> 3810616SSebastien.Roy@Sun.COM #include <inet/iptun.h> 3910616SSebastien.Roy@Sun.COM #include <sys/dls.h> 4010616SSebastien.Roy@Sun.COM #include <libdlpi.h> 4110616SSebastien.Roy@Sun.COM #include <libdladm_impl.h> 4210616SSebastien.Roy@Sun.COM #include <libdllink.h> 4310616SSebastien.Roy@Sun.COM #include <libdliptun.h> 4410616SSebastien.Roy@Sun.COM 4510616SSebastien.Roy@Sun.COM /* 4610616SSebastien.Roy@Sun.COM * IP Tunneling Administration Library. 4710616SSebastien.Roy@Sun.COM * This library is used by dladm(1M) and to configure IP tunnel links. 4810616SSebastien.Roy@Sun.COM */ 4910616SSebastien.Roy@Sun.COM 5010616SSebastien.Roy@Sun.COM #define IPTUN_CONF_TYPE "type" 5110616SSebastien.Roy@Sun.COM #define IPTUN_CONF_LADDR "laddr" 5210616SSebastien.Roy@Sun.COM #define IPTUN_CONF_RADDR "raddr" 5310616SSebastien.Roy@Sun.COM 5410616SSebastien.Roy@Sun.COM /* 5510616SSebastien.Roy@Sun.COM * If IPTUN_CREATE and IPTUN_MODIFY include IPsec policy and IPsec hasn't 5610616SSebastien.Roy@Sun.COM * loaded yet, the ioctls may return EAGAIN. We try the ioctl 5710616SSebastien.Roy@Sun.COM * IPTUN_IOCTL_ATTEMPT_LIMIT times and wait IPTUN_IOCTL_ATTEMPT_INTERVAL 5810616SSebastien.Roy@Sun.COM * microseconds between attempts. 5910616SSebastien.Roy@Sun.COM */ 6010616SSebastien.Roy@Sun.COM #define IPTUN_IOCTL_ATTEMPT_LIMIT 3 6110616SSebastien.Roy@Sun.COM #define IPTUN_IOCTL_ATTEMPT_INTERVAL 10000 6210616SSebastien.Roy@Sun.COM 6310616SSebastien.Roy@Sun.COM dladm_status_t 6410616SSebastien.Roy@Sun.COM i_iptun_ioctl(dladm_handle_t handle, int cmd, void *dp) 6510616SSebastien.Roy@Sun.COM { 6610616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 6710616SSebastien.Roy@Sun.COM uint_t attempt; 6810616SSebastien.Roy@Sun.COM 6910616SSebastien.Roy@Sun.COM for (attempt = 0; attempt < IPTUN_IOCTL_ATTEMPT_LIMIT; attempt++) { 7010616SSebastien.Roy@Sun.COM if (attempt != 0) 7110616SSebastien.Roy@Sun.COM (void) usleep(IPTUN_IOCTL_ATTEMPT_INTERVAL); 7210616SSebastien.Roy@Sun.COM status = (ioctl(dladm_dld_fd(handle), cmd, dp) == 0) ? 7310616SSebastien.Roy@Sun.COM DLADM_STATUS_OK : dladm_errno2status(errno); 7410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_TRYAGAIN) 7510616SSebastien.Roy@Sun.COM break; 7610616SSebastien.Roy@Sun.COM } 7710616SSebastien.Roy@Sun.COM return (status); 7810616SSebastien.Roy@Sun.COM } 7910616SSebastien.Roy@Sun.COM 8010616SSebastien.Roy@Sun.COM /* 8110616SSebastien.Roy@Sun.COM * Given tunnel paramaters as supplied by a library consumer, fill in kernel 8210616SSebastien.Roy@Sun.COM * parameters to be passed down to the iptun control device. 8310616SSebastien.Roy@Sun.COM */ 8410616SSebastien.Roy@Sun.COM static dladm_status_t 8510616SSebastien.Roy@Sun.COM i_iptun_kparams(dladm_handle_t handle, const iptun_params_t *params, 8610616SSebastien.Roy@Sun.COM iptun_kparams_t *ik) 8710616SSebastien.Roy@Sun.COM { 8810616SSebastien.Roy@Sun.COM dladm_status_t status; 8910616SSebastien.Roy@Sun.COM struct addrinfo *ai, hints; 9010616SSebastien.Roy@Sun.COM iptun_kparams_t tmpik; 9110616SSebastien.Roy@Sun.COM iptun_type_t iptuntype = IPTUN_TYPE_UNKNOWN; 9210616SSebastien.Roy@Sun.COM 9310616SSebastien.Roy@Sun.COM (void) memset(ik, 0, sizeof (*ik)); 9410616SSebastien.Roy@Sun.COM 9510616SSebastien.Roy@Sun.COM ik->iptun_kparam_linkid = params->iptun_param_linkid; 9610616SSebastien.Roy@Sun.COM 9710616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_TYPE) { 9810616SSebastien.Roy@Sun.COM ik->iptun_kparam_type = iptuntype = params->iptun_param_type; 9910616SSebastien.Roy@Sun.COM ik->iptun_kparam_flags |= IPTUN_KPARAM_TYPE; 10010616SSebastien.Roy@Sun.COM } 10110616SSebastien.Roy@Sun.COM 10210616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)) { 10310616SSebastien.Roy@Sun.COM if (iptuntype == IPTUN_TYPE_UNKNOWN) { 10410616SSebastien.Roy@Sun.COM /* 10510616SSebastien.Roy@Sun.COM * We need to get the type of this existing tunnel in 10610616SSebastien.Roy@Sun.COM * order to validate and/or look up the right kind of 10710616SSebastien.Roy@Sun.COM * IP address. 10810616SSebastien.Roy@Sun.COM */ 10910616SSebastien.Roy@Sun.COM tmpik.iptun_kparam_linkid = params->iptun_param_linkid; 11010616SSebastien.Roy@Sun.COM status = i_iptun_ioctl(handle, IPTUN_INFO, &tmpik); 11110616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 11210616SSebastien.Roy@Sun.COM return (status); 11310616SSebastien.Roy@Sun.COM iptuntype = tmpik.iptun_kparam_type; 11410616SSebastien.Roy@Sun.COM } 11510616SSebastien.Roy@Sun.COM 11610616SSebastien.Roy@Sun.COM (void) memset(&hints, 0, sizeof (hints)); 11710616SSebastien.Roy@Sun.COM switch (iptuntype) { 11810616SSebastien.Roy@Sun.COM case IPTUN_TYPE_IPV4: 11910616SSebastien.Roy@Sun.COM case IPTUN_TYPE_6TO4: 12010616SSebastien.Roy@Sun.COM hints.ai_family = AF_INET; 12110616SSebastien.Roy@Sun.COM break; 12210616SSebastien.Roy@Sun.COM case IPTUN_TYPE_IPV6: 12310616SSebastien.Roy@Sun.COM hints.ai_family = AF_INET6; 12410616SSebastien.Roy@Sun.COM break; 12510616SSebastien.Roy@Sun.COM } 12610616SSebastien.Roy@Sun.COM } 12710616SSebastien.Roy@Sun.COM 12810616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { 12910616SSebastien.Roy@Sun.COM if (getaddrinfo(params->iptun_param_laddr, NULL, &hints, &ai) != 13010616SSebastien.Roy@Sun.COM 0) 13110616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNLADDR); 13210616SSebastien.Roy@Sun.COM if (ai->ai_next != NULL) { 13310616SSebastien.Roy@Sun.COM freeaddrinfo(ai); 13410616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNLADDR); 13510616SSebastien.Roy@Sun.COM } 13610616SSebastien.Roy@Sun.COM (void) memcpy(&ik->iptun_kparam_laddr, ai->ai_addr, 13710616SSebastien.Roy@Sun.COM ai->ai_addrlen); 13810616SSebastien.Roy@Sun.COM ik->iptun_kparam_flags |= IPTUN_KPARAM_LADDR; 13910616SSebastien.Roy@Sun.COM freeaddrinfo(ai); 14010616SSebastien.Roy@Sun.COM } 14110616SSebastien.Roy@Sun.COM 14210616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { 14310616SSebastien.Roy@Sun.COM if (getaddrinfo(params->iptun_param_raddr, NULL, &hints, &ai) != 14410616SSebastien.Roy@Sun.COM 0) 14510616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNRADDR); 14610616SSebastien.Roy@Sun.COM if (ai->ai_next != NULL) { 14710616SSebastien.Roy@Sun.COM freeaddrinfo(ai); 14810616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNRADDR); 14910616SSebastien.Roy@Sun.COM } 15010616SSebastien.Roy@Sun.COM (void) memcpy(&ik->iptun_kparam_raddr, ai->ai_addr, 15110616SSebastien.Roy@Sun.COM ai->ai_addrlen); 15210616SSebastien.Roy@Sun.COM ik->iptun_kparam_flags |= IPTUN_KPARAM_RADDR; 15310616SSebastien.Roy@Sun.COM freeaddrinfo(ai); 15410616SSebastien.Roy@Sun.COM } 15510616SSebastien.Roy@Sun.COM 15610616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_SECINFO) { 15710616SSebastien.Roy@Sun.COM ik->iptun_kparam_secinfo = params->iptun_param_secinfo; 15810616SSebastien.Roy@Sun.COM ik->iptun_kparam_flags |= IPTUN_KPARAM_SECINFO; 15910616SSebastien.Roy@Sun.COM } 16010616SSebastien.Roy@Sun.COM 16110616SSebastien.Roy@Sun.COM return (DLADM_STATUS_OK); 16210616SSebastien.Roy@Sun.COM } 16310616SSebastien.Roy@Sun.COM 16410616SSebastien.Roy@Sun.COM /* 16510616SSebastien.Roy@Sun.COM * The inverse of i_iptun_kparams(). Given kernel tunnel paramaters as 16610616SSebastien.Roy@Sun.COM * returned from an IPTUN_INFO ioctl, fill in tunnel parameters. 16710616SSebastien.Roy@Sun.COM */ 16810616SSebastien.Roy@Sun.COM static dladm_status_t 16910616SSebastien.Roy@Sun.COM i_iptun_params(const iptun_kparams_t *ik, iptun_params_t *params) 17010616SSebastien.Roy@Sun.COM { 17110616SSebastien.Roy@Sun.COM socklen_t salen; 17210616SSebastien.Roy@Sun.COM 17310616SSebastien.Roy@Sun.COM (void) memset(params, 0, sizeof (*params)); 17410616SSebastien.Roy@Sun.COM 17510616SSebastien.Roy@Sun.COM params->iptun_param_linkid = ik->iptun_kparam_linkid; 17610616SSebastien.Roy@Sun.COM 17710616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_TYPE) { 17810616SSebastien.Roy@Sun.COM params->iptun_param_type = ik->iptun_kparam_type; 17910616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_TYPE; 18010616SSebastien.Roy@Sun.COM } 18110616SSebastien.Roy@Sun.COM 18210616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_LADDR) { 18310616SSebastien.Roy@Sun.COM salen = ik->iptun_kparam_laddr.ss_family == AF_INET ? 18410616SSebastien.Roy@Sun.COM sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); 18510616SSebastien.Roy@Sun.COM if (getnameinfo((const struct sockaddr *) 18610616SSebastien.Roy@Sun.COM &ik->iptun_kparam_laddr, salen, params->iptun_param_laddr, 18710616SSebastien.Roy@Sun.COM sizeof (params->iptun_param_laddr), NULL, 0, 18810616SSebastien.Roy@Sun.COM NI_NUMERICHOST) != 0) { 18910616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNLADDR); 19010616SSebastien.Roy@Sun.COM } 19110616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_LADDR; 19210616SSebastien.Roy@Sun.COM } 19310616SSebastien.Roy@Sun.COM 19410616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_RADDR) { 19510616SSebastien.Roy@Sun.COM salen = ik->iptun_kparam_raddr.ss_family == AF_INET ? 19610616SSebastien.Roy@Sun.COM sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); 19710616SSebastien.Roy@Sun.COM if (getnameinfo((const struct sockaddr *) 19810616SSebastien.Roy@Sun.COM &ik->iptun_kparam_raddr, salen, params->iptun_param_raddr, 19910616SSebastien.Roy@Sun.COM sizeof (params->iptun_param_raddr), NULL, 0, 20010616SSebastien.Roy@Sun.COM NI_NUMERICHOST) != 0) { 20110616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADIPTUNRADDR); 20210616SSebastien.Roy@Sun.COM } 20310616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_RADDR; 20410616SSebastien.Roy@Sun.COM } 20510616SSebastien.Roy@Sun.COM 20610616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_SECINFO) { 20710616SSebastien.Roy@Sun.COM params->iptun_param_secinfo = ik->iptun_kparam_secinfo; 20810616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_SECINFO; 20910616SSebastien.Roy@Sun.COM } 21010616SSebastien.Roy@Sun.COM 21110616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_IMPLICIT) 21210616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_IMPLICIT; 21310616SSebastien.Roy@Sun.COM 21410616SSebastien.Roy@Sun.COM if (ik->iptun_kparam_flags & IPTUN_KPARAM_IPSECPOL) 21510616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_IPSECPOL; 21610616SSebastien.Roy@Sun.COM 21710616SSebastien.Roy@Sun.COM return (DLADM_STATUS_OK); 21810616SSebastien.Roy@Sun.COM } 21910616SSebastien.Roy@Sun.COM 22010616SSebastien.Roy@Sun.COM dladm_status_t 22110616SSebastien.Roy@Sun.COM i_iptun_get_sysparams(dladm_handle_t handle, iptun_params_t *params) 22210616SSebastien.Roy@Sun.COM { 22310616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 22410616SSebastien.Roy@Sun.COM iptun_kparams_t ik; 22510616SSebastien.Roy@Sun.COM 22610616SSebastien.Roy@Sun.COM ik.iptun_kparam_linkid = params->iptun_param_linkid; 22710616SSebastien.Roy@Sun.COM status = i_iptun_ioctl(handle, IPTUN_INFO, &ik); 22810616SSebastien.Roy@Sun.COM if (status == DLADM_STATUS_OK) 22910616SSebastien.Roy@Sun.COM status = i_iptun_params(&ik, params); 23010616SSebastien.Roy@Sun.COM return (status); 23110616SSebastien.Roy@Sun.COM } 23210616SSebastien.Roy@Sun.COM 23310616SSebastien.Roy@Sun.COM /* 23410616SSebastien.Roy@Sun.COM * Read tunnel parameters from persistent storage. Note that the tunnel type 23510616SSebastien.Roy@Sun.COM * is the only thing which must always be in the configuratioh. All other 23610616SSebastien.Roy@Sun.COM * parameters (currently the source and destination addresses) may or may not 23710616SSebastien.Roy@Sun.COM * have been configured, and therefore may not have been set. 23810616SSebastien.Roy@Sun.COM */ 23910616SSebastien.Roy@Sun.COM static dladm_status_t 24010616SSebastien.Roy@Sun.COM i_iptun_get_dbparams(dladm_handle_t handle, iptun_params_t *params) 24110616SSebastien.Roy@Sun.COM { 24210616SSebastien.Roy@Sun.COM dladm_status_t status; 24310616SSebastien.Roy@Sun.COM dladm_conf_t conf; 24410616SSebastien.Roy@Sun.COM datalink_class_t class; 24510616SSebastien.Roy@Sun.COM uint64_t temp; 24610616SSebastien.Roy@Sun.COM 24710616SSebastien.Roy@Sun.COM /* First, make sure that this is an IP tunnel. */ 24810616SSebastien.Roy@Sun.COM if ((status = dladm_datalink_id2info(handle, params->iptun_param_linkid, 24910616SSebastien.Roy@Sun.COM NULL, &class, NULL, NULL, 0)) != DLADM_STATUS_OK) 25010616SSebastien.Roy@Sun.COM return (status); 25110616SSebastien.Roy@Sun.COM if (class != DATALINK_CLASS_IPTUN) 25210616SSebastien.Roy@Sun.COM return (DLADM_STATUS_LINKINVAL); 25310616SSebastien.Roy@Sun.COM 254*12824SCathy.Zhou@Sun.COM if ((status = dladm_getsnap_conf(handle, params->iptun_param_linkid, 255*12824SCathy.Zhou@Sun.COM &conf)) != DLADM_STATUS_OK) { 25610616SSebastien.Roy@Sun.COM return (status); 257*12824SCathy.Zhou@Sun.COM } 25810616SSebastien.Roy@Sun.COM 25910616SSebastien.Roy@Sun.COM params->iptun_param_flags = 0; 26010616SSebastien.Roy@Sun.COM 26110616SSebastien.Roy@Sun.COM if ((status = dladm_get_conf_field(handle, conf, IPTUN_CONF_TYPE, &temp, 26210616SSebastien.Roy@Sun.COM sizeof (temp))) != DLADM_STATUS_OK) 26310616SSebastien.Roy@Sun.COM goto done; 26410616SSebastien.Roy@Sun.COM params->iptun_param_type = (iptun_type_t)temp; 26510616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_TYPE; 26610616SSebastien.Roy@Sun.COM 26710616SSebastien.Roy@Sun.COM if (dladm_get_conf_field(handle, conf, IPTUN_CONF_LADDR, 26810616SSebastien.Roy@Sun.COM params->iptun_param_laddr, sizeof (params->iptun_param_laddr)) == 26910616SSebastien.Roy@Sun.COM DLADM_STATUS_OK) 27010616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_LADDR; 27110616SSebastien.Roy@Sun.COM 27210616SSebastien.Roy@Sun.COM if (dladm_get_conf_field(handle, conf, IPTUN_CONF_RADDR, 27310616SSebastien.Roy@Sun.COM params->iptun_param_raddr, sizeof (params->iptun_param_raddr)) == 27410616SSebastien.Roy@Sun.COM DLADM_STATUS_OK) 27510616SSebastien.Roy@Sun.COM params->iptun_param_flags |= IPTUN_PARAM_RADDR; 27610616SSebastien.Roy@Sun.COM 27710616SSebastien.Roy@Sun.COM done: 27810616SSebastien.Roy@Sun.COM dladm_destroy_conf(handle, conf); 27910616SSebastien.Roy@Sun.COM return (status); 28010616SSebastien.Roy@Sun.COM } 28110616SSebastien.Roy@Sun.COM 28210616SSebastien.Roy@Sun.COM static dladm_status_t 28310616SSebastien.Roy@Sun.COM i_iptun_create_sys(dladm_handle_t handle, iptun_params_t *params) 28410616SSebastien.Roy@Sun.COM { 28510616SSebastien.Roy@Sun.COM iptun_kparams_t ik; 28610616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 28710616SSebastien.Roy@Sun.COM 28810616SSebastien.Roy@Sun.COM /* The tunnel type is required for creation. */ 28910616SSebastien.Roy@Sun.COM if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE)) 29010616SSebastien.Roy@Sun.COM return (DLADM_STATUS_IPTUNTYPEREQD); 29110616SSebastien.Roy@Sun.COM 29210616SSebastien.Roy@Sun.COM if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK) 29310616SSebastien.Roy@Sun.COM status = i_iptun_ioctl(handle, IPTUN_CREATE, &ik); 29410616SSebastien.Roy@Sun.COM return (status); 29510616SSebastien.Roy@Sun.COM } 29610616SSebastien.Roy@Sun.COM 29710616SSebastien.Roy@Sun.COM static dladm_status_t 29810616SSebastien.Roy@Sun.COM i_iptun_create_db(dladm_handle_t handle, const char *name, 29910616SSebastien.Roy@Sun.COM iptun_params_t *params, uint32_t media) 30010616SSebastien.Roy@Sun.COM { 30110616SSebastien.Roy@Sun.COM dladm_conf_t conf; 30210616SSebastien.Roy@Sun.COM dladm_status_t status; 30310616SSebastien.Roy@Sun.COM uint64_t storage; 30410616SSebastien.Roy@Sun.COM 30510616SSebastien.Roy@Sun.COM status = dladm_create_conf(handle, name, params->iptun_param_linkid, 30610616SSebastien.Roy@Sun.COM DATALINK_CLASS_IPTUN, media, &conf); 30710616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 30810616SSebastien.Roy@Sun.COM return (status); 30910616SSebastien.Roy@Sun.COM 31010616SSebastien.Roy@Sun.COM assert(params->iptun_param_flags & IPTUN_PARAM_TYPE); 31110616SSebastien.Roy@Sun.COM storage = params->iptun_param_type; 31210616SSebastien.Roy@Sun.COM status = dladm_set_conf_field(handle, conf, IPTUN_CONF_TYPE, 31310616SSebastien.Roy@Sun.COM DLADM_TYPE_UINT64, &storage); 31410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 31510616SSebastien.Roy@Sun.COM goto done; 31610616SSebastien.Roy@Sun.COM 31710616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { 31810616SSebastien.Roy@Sun.COM status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR, 31910616SSebastien.Roy@Sun.COM DLADM_TYPE_STR, params->iptun_param_laddr); 32010616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 32110616SSebastien.Roy@Sun.COM goto done; 32210616SSebastien.Roy@Sun.COM } 32310616SSebastien.Roy@Sun.COM 32410616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { 32510616SSebastien.Roy@Sun.COM status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR, 32610616SSebastien.Roy@Sun.COM DLADM_TYPE_STR, params->iptun_param_raddr); 32710616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 32810616SSebastien.Roy@Sun.COM goto done; 32910616SSebastien.Roy@Sun.COM } 33010616SSebastien.Roy@Sun.COM 33110616SSebastien.Roy@Sun.COM status = dladm_write_conf(handle, conf); 33210616SSebastien.Roy@Sun.COM 33310616SSebastien.Roy@Sun.COM done: 33410616SSebastien.Roy@Sun.COM dladm_destroy_conf(handle, conf); 33510616SSebastien.Roy@Sun.COM return (status); 33610616SSebastien.Roy@Sun.COM } 33710616SSebastien.Roy@Sun.COM 33810616SSebastien.Roy@Sun.COM static dladm_status_t 33910616SSebastien.Roy@Sun.COM i_iptun_delete_sys(dladm_handle_t handle, datalink_id_t linkid) 34010616SSebastien.Roy@Sun.COM { 34110616SSebastien.Roy@Sun.COM dladm_status_t status; 34210616SSebastien.Roy@Sun.COM 34310616SSebastien.Roy@Sun.COM status = i_iptun_ioctl(handle, IPTUN_DELETE, &linkid); 34410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 34510616SSebastien.Roy@Sun.COM return (status); 34610616SSebastien.Roy@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_ACTIVE); 34710616SSebastien.Roy@Sun.COM return (DLADM_STATUS_OK); 34810616SSebastien.Roy@Sun.COM } 34910616SSebastien.Roy@Sun.COM 35010616SSebastien.Roy@Sun.COM static dladm_status_t 35110616SSebastien.Roy@Sun.COM i_iptun_modify_sys(dladm_handle_t handle, const iptun_params_t *params) 35210616SSebastien.Roy@Sun.COM { 35310616SSebastien.Roy@Sun.COM iptun_kparams_t ik; 35410616SSebastien.Roy@Sun.COM dladm_status_t status; 35510616SSebastien.Roy@Sun.COM 35610616SSebastien.Roy@Sun.COM if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK) 35710616SSebastien.Roy@Sun.COM status = i_iptun_ioctl(handle, IPTUN_MODIFY, &ik); 35810616SSebastien.Roy@Sun.COM return (status); 35910616SSebastien.Roy@Sun.COM } 36010616SSebastien.Roy@Sun.COM 36110616SSebastien.Roy@Sun.COM static dladm_status_t 36210616SSebastien.Roy@Sun.COM i_iptun_modify_db(dladm_handle_t handle, const iptun_params_t *params) 36310616SSebastien.Roy@Sun.COM { 36410616SSebastien.Roy@Sun.COM dladm_conf_t conf; 36510616SSebastien.Roy@Sun.COM dladm_status_t status; 36610616SSebastien.Roy@Sun.COM 36710616SSebastien.Roy@Sun.COM assert(params->iptun_param_flags & 36810616SSebastien.Roy@Sun.COM (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)); 36910616SSebastien.Roy@Sun.COM 37010616SSebastien.Roy@Sun.COM /* 37110616SSebastien.Roy@Sun.COM * The only parameters that can be modified persistently are the local 37210616SSebastien.Roy@Sun.COM * and remote addresses. 37310616SSebastien.Roy@Sun.COM */ 37410616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & ~(IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)) 37510616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADARG); 37610616SSebastien.Roy@Sun.COM 377*12824SCathy.Zhou@Sun.COM status = dladm_open_conf(handle, params->iptun_param_linkid, &conf); 37810616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 37910616SSebastien.Roy@Sun.COM return (status); 38010616SSebastien.Roy@Sun.COM 38110616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { 38210616SSebastien.Roy@Sun.COM status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR, 38310616SSebastien.Roy@Sun.COM DLADM_TYPE_STR, (void *)params->iptun_param_laddr); 38410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 38510616SSebastien.Roy@Sun.COM goto done; 38610616SSebastien.Roy@Sun.COM } 38710616SSebastien.Roy@Sun.COM 38810616SSebastien.Roy@Sun.COM if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { 38910616SSebastien.Roy@Sun.COM status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR, 39010616SSebastien.Roy@Sun.COM DLADM_TYPE_STR, (void *)params->iptun_param_raddr); 39110616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 39210616SSebastien.Roy@Sun.COM goto done; 39310616SSebastien.Roy@Sun.COM } 39410616SSebastien.Roy@Sun.COM 39510616SSebastien.Roy@Sun.COM status = dladm_write_conf(handle, conf); 39610616SSebastien.Roy@Sun.COM 39710616SSebastien.Roy@Sun.COM done: 39810616SSebastien.Roy@Sun.COM dladm_destroy_conf(handle, conf); 39910616SSebastien.Roy@Sun.COM return (status); 40010616SSebastien.Roy@Sun.COM } 40110616SSebastien.Roy@Sun.COM 40210616SSebastien.Roy@Sun.COM dladm_status_t 40310616SSebastien.Roy@Sun.COM dladm_iptun_create(dladm_handle_t handle, const char *name, 40410616SSebastien.Roy@Sun.COM iptun_params_t *params, uint32_t flags) 40510616SSebastien.Roy@Sun.COM { 40610616SSebastien.Roy@Sun.COM dladm_status_t status; 40710616SSebastien.Roy@Sun.COM uint32_t linkmgmt_flags = flags; 40810616SSebastien.Roy@Sun.COM uint32_t media; 40910616SSebastien.Roy@Sun.COM 41010616SSebastien.Roy@Sun.COM if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE)) 41110616SSebastien.Roy@Sun.COM return (DLADM_STATUS_IPTUNTYPEREQD); 41210616SSebastien.Roy@Sun.COM 41310616SSebastien.Roy@Sun.COM switch (params->iptun_param_type) { 41410616SSebastien.Roy@Sun.COM case IPTUN_TYPE_IPV4: 41510616SSebastien.Roy@Sun.COM media = DL_IPV4; 41610616SSebastien.Roy@Sun.COM break; 41710616SSebastien.Roy@Sun.COM case IPTUN_TYPE_IPV6: 41810616SSebastien.Roy@Sun.COM media = DL_IPV6; 41910616SSebastien.Roy@Sun.COM break; 42010616SSebastien.Roy@Sun.COM case IPTUN_TYPE_6TO4: 42110616SSebastien.Roy@Sun.COM media = DL_6TO4; 42210616SSebastien.Roy@Sun.COM break; 42310616SSebastien.Roy@Sun.COM default: 42410616SSebastien.Roy@Sun.COM return (DLADM_STATUS_IPTUNTYPE); 42510616SSebastien.Roy@Sun.COM } 42610616SSebastien.Roy@Sun.COM 42710616SSebastien.Roy@Sun.COM status = dladm_create_datalink_id(handle, name, DATALINK_CLASS_IPTUN, 42810616SSebastien.Roy@Sun.COM media, linkmgmt_flags, ¶ms->iptun_param_linkid); 42910616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 43010616SSebastien.Roy@Sun.COM return (status); 43110616SSebastien.Roy@Sun.COM 43210616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_PERSIST) { 43310616SSebastien.Roy@Sun.COM status = i_iptun_create_db(handle, name, params, media); 43410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 43510616SSebastien.Roy@Sun.COM goto done; 43610616SSebastien.Roy@Sun.COM } 43710616SSebastien.Roy@Sun.COM 43810616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_ACTIVE) { 43910616SSebastien.Roy@Sun.COM status = i_iptun_create_sys(handle, params); 44010616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) { 44110616SSebastien.Roy@Sun.COM (void) dladm_remove_conf(handle, 44210616SSebastien.Roy@Sun.COM params->iptun_param_linkid); 44310616SSebastien.Roy@Sun.COM } 44410616SSebastien.Roy@Sun.COM } 44510616SSebastien.Roy@Sun.COM 44610616SSebastien.Roy@Sun.COM done: 44710616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) { 44810616SSebastien.Roy@Sun.COM (void) dladm_destroy_datalink_id(handle, 44910616SSebastien.Roy@Sun.COM params->iptun_param_linkid, flags); 45010616SSebastien.Roy@Sun.COM } 45110616SSebastien.Roy@Sun.COM return (status); 45210616SSebastien.Roy@Sun.COM } 45310616SSebastien.Roy@Sun.COM 45410616SSebastien.Roy@Sun.COM dladm_status_t 45510616SSebastien.Roy@Sun.COM dladm_iptun_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 45610616SSebastien.Roy@Sun.COM { 45710616SSebastien.Roy@Sun.COM dladm_status_t status; 45810616SSebastien.Roy@Sun.COM datalink_class_t class; 45910616SSebastien.Roy@Sun.COM 46010616SSebastien.Roy@Sun.COM /* First, make sure that this is an IP tunnel. */ 46110616SSebastien.Roy@Sun.COM if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, 46210616SSebastien.Roy@Sun.COM NULL, 0)) != DLADM_STATUS_OK) 46310616SSebastien.Roy@Sun.COM return (status); 46410616SSebastien.Roy@Sun.COM if (class != DATALINK_CLASS_IPTUN) 46510616SSebastien.Roy@Sun.COM return (DLADM_STATUS_LINKINVAL); 46610616SSebastien.Roy@Sun.COM 46710616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_ACTIVE) { 46810616SSebastien.Roy@Sun.COM /* 46910616SSebastien.Roy@Sun.COM * Note that if i_iptun_delete_sys() fails with 47010616SSebastien.Roy@Sun.COM * DLADM_STATUS_NOTFOUND and the caller also wishes to delete 47110616SSebastien.Roy@Sun.COM * the persistent configuration, we still fall through to the 47210616SSebastien.Roy@Sun.COM * DLADM_OPT_PERSIST case in case the tunnel only exists 47310616SSebastien.Roy@Sun.COM * persistently. 47410616SSebastien.Roy@Sun.COM */ 47510616SSebastien.Roy@Sun.COM status = i_iptun_delete_sys(handle, linkid); 47610616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK && 47710616SSebastien.Roy@Sun.COM (status != DLADM_STATUS_NOTFOUND || 47810616SSebastien.Roy@Sun.COM !(flags & DLADM_OPT_PERSIST))) 47910616SSebastien.Roy@Sun.COM return (status); 48010616SSebastien.Roy@Sun.COM } 48110616SSebastien.Roy@Sun.COM 48210616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_PERSIST) { 48310616SSebastien.Roy@Sun.COM (void) dladm_remove_conf(handle, linkid); 48410616SSebastien.Roy@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, 48510616SSebastien.Roy@Sun.COM DLADM_OPT_PERSIST); 48610616SSebastien.Roy@Sun.COM } 48710616SSebastien.Roy@Sun.COM return (DLADM_STATUS_OK); 48810616SSebastien.Roy@Sun.COM } 48910616SSebastien.Roy@Sun.COM 49010616SSebastien.Roy@Sun.COM dladm_status_t 49110616SSebastien.Roy@Sun.COM dladm_iptun_modify(dladm_handle_t handle, const iptun_params_t *params, 49210616SSebastien.Roy@Sun.COM uint32_t flags) 49310616SSebastien.Roy@Sun.COM { 49410616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 49510616SSebastien.Roy@Sun.COM iptun_params_t old_params; 49610616SSebastien.Roy@Sun.COM 49710616SSebastien.Roy@Sun.COM /* 49810616SSebastien.Roy@Sun.COM * We can only modify the tunnel source, tunnel destination, or IPsec 49910616SSebastien.Roy@Sun.COM * policy. 50010616SSebastien.Roy@Sun.COM */ 50110616SSebastien.Roy@Sun.COM if (!(params->iptun_param_flags & 50210616SSebastien.Roy@Sun.COM (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR|IPTUN_PARAM_SECINFO))) 50310616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADARG); 50410616SSebastien.Roy@Sun.COM 50510616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_PERSIST) { 50610616SSebastien.Roy@Sun.COM /* 50710616SSebastien.Roy@Sun.COM * Before we change the database, save the old configuration 50810616SSebastien.Roy@Sun.COM * so that we can revert back if an error occurs. 50910616SSebastien.Roy@Sun.COM */ 51010616SSebastien.Roy@Sun.COM old_params.iptun_param_linkid = params->iptun_param_linkid; 51110616SSebastien.Roy@Sun.COM status = i_iptun_get_dbparams(handle, &old_params); 51210616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 51310616SSebastien.Roy@Sun.COM return (status); 51410616SSebastien.Roy@Sun.COM /* we'll only need to revert the parameters being modified */ 51510616SSebastien.Roy@Sun.COM old_params.iptun_param_flags = params->iptun_param_flags; 51610616SSebastien.Roy@Sun.COM 51710616SSebastien.Roy@Sun.COM status = i_iptun_modify_db(handle, params); 51810616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 51910616SSebastien.Roy@Sun.COM return (status); 52010616SSebastien.Roy@Sun.COM } 52110616SSebastien.Roy@Sun.COM 52210616SSebastien.Roy@Sun.COM if (flags & DLADM_OPT_ACTIVE) { 52310616SSebastien.Roy@Sun.COM status = i_iptun_modify_sys(handle, params); 52410616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) { 52510616SSebastien.Roy@Sun.COM (void) i_iptun_modify_db(handle, &old_params); 52610616SSebastien.Roy@Sun.COM } 52710616SSebastien.Roy@Sun.COM } 52810616SSebastien.Roy@Sun.COM 52910616SSebastien.Roy@Sun.COM return (status); 53010616SSebastien.Roy@Sun.COM } 53110616SSebastien.Roy@Sun.COM 53210616SSebastien.Roy@Sun.COM dladm_status_t 53310616SSebastien.Roy@Sun.COM dladm_iptun_getparams(dladm_handle_t handle, iptun_params_t *params, 53410616SSebastien.Roy@Sun.COM uint32_t flags) 53510616SSebastien.Roy@Sun.COM { 53610616SSebastien.Roy@Sun.COM if (flags == DLADM_OPT_ACTIVE) 53710616SSebastien.Roy@Sun.COM return (i_iptun_get_sysparams(handle, params)); 53810616SSebastien.Roy@Sun.COM else if (flags == DLADM_OPT_PERSIST) 53910616SSebastien.Roy@Sun.COM return (i_iptun_get_dbparams(handle, params)); 54010616SSebastien.Roy@Sun.COM else 54110616SSebastien.Roy@Sun.COM return (DLADM_STATUS_BADARG); 54210616SSebastien.Roy@Sun.COM } 54310616SSebastien.Roy@Sun.COM 54410616SSebastien.Roy@Sun.COM static int 54510616SSebastien.Roy@Sun.COM i_iptun_up(dladm_handle_t handle, datalink_id_t linkid, void *arg) 54610616SSebastien.Roy@Sun.COM { 54710616SSebastien.Roy@Sun.COM dladm_status_t *statusp = arg; 54810616SSebastien.Roy@Sun.COM dladm_status_t status; 54910616SSebastien.Roy@Sun.COM iptun_params_t params; 55010616SSebastien.Roy@Sun.COM boolean_t id_up = B_FALSE; 55110616SSebastien.Roy@Sun.COM 55210616SSebastien.Roy@Sun.COM status = dladm_up_datalink_id(handle, linkid); 55310616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK) 55410616SSebastien.Roy@Sun.COM goto done; 55510616SSebastien.Roy@Sun.COM id_up = B_TRUE; 55610616SSebastien.Roy@Sun.COM 55710616SSebastien.Roy@Sun.COM (void) memset(¶ms, 0, sizeof (params)); 55810616SSebastien.Roy@Sun.COM 55910616SSebastien.Roy@Sun.COM params.iptun_param_linkid = linkid; 56010616SSebastien.Roy@Sun.COM if ((status = i_iptun_get_dbparams(handle, ¶ms)) == DLADM_STATUS_OK) 56110616SSebastien.Roy@Sun.COM status = i_iptun_create_sys(handle, ¶ms); 56210616SSebastien.Roy@Sun.COM done: 56310616SSebastien.Roy@Sun.COM if (statusp != NULL) 56410616SSebastien.Roy@Sun.COM *statusp = status; 56510616SSebastien.Roy@Sun.COM if (status != DLADM_STATUS_OK && id_up) { 56610616SSebastien.Roy@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, 56710616SSebastien.Roy@Sun.COM DLADM_OPT_ACTIVE); 56810616SSebastien.Roy@Sun.COM } 56910616SSebastien.Roy@Sun.COM return (DLADM_WALK_CONTINUE); 57010616SSebastien.Roy@Sun.COM } 57110616SSebastien.Roy@Sun.COM 57210616SSebastien.Roy@Sun.COM static int 57310616SSebastien.Roy@Sun.COM i_iptun_down(dladm_handle_t handle, datalink_id_t linkid, void *arg) 57410616SSebastien.Roy@Sun.COM { 57510616SSebastien.Roy@Sun.COM dladm_status_t *statusp = arg; 57610616SSebastien.Roy@Sun.COM dladm_status_t status; 57710616SSebastien.Roy@Sun.COM 57810616SSebastien.Roy@Sun.COM status = i_iptun_delete_sys(handle, linkid); 57910616SSebastien.Roy@Sun.COM if (statusp != NULL) 58010616SSebastien.Roy@Sun.COM *statusp = status; 58110616SSebastien.Roy@Sun.COM return (DLADM_WALK_CONTINUE); 58210616SSebastien.Roy@Sun.COM } 58310616SSebastien.Roy@Sun.COM 58410616SSebastien.Roy@Sun.COM /* ARGSUSED */ 58510616SSebastien.Roy@Sun.COM dladm_status_t 58610616SSebastien.Roy@Sun.COM dladm_iptun_up(dladm_handle_t handle, datalink_id_t linkid) 58710616SSebastien.Roy@Sun.COM { 58810616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 58910616SSebastien.Roy@Sun.COM 59010616SSebastien.Roy@Sun.COM if (linkid == DATALINK_ALL_LINKID) { 59110616SSebastien.Roy@Sun.COM (void) dladm_walk_datalink_id(i_iptun_up, handle, NULL, 59210616SSebastien.Roy@Sun.COM DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE, 59310616SSebastien.Roy@Sun.COM DLADM_OPT_PERSIST); 59410616SSebastien.Roy@Sun.COM } else { 59510616SSebastien.Roy@Sun.COM (void) i_iptun_up(handle, linkid, &status); 59610616SSebastien.Roy@Sun.COM } 59710616SSebastien.Roy@Sun.COM return (status); 59810616SSebastien.Roy@Sun.COM } 59910616SSebastien.Roy@Sun.COM 60010616SSebastien.Roy@Sun.COM dladm_status_t 60110616SSebastien.Roy@Sun.COM dladm_iptun_down(dladm_handle_t handle, datalink_id_t linkid) 60210616SSebastien.Roy@Sun.COM { 60310616SSebastien.Roy@Sun.COM dladm_status_t status = DLADM_STATUS_OK; 60410616SSebastien.Roy@Sun.COM 60510616SSebastien.Roy@Sun.COM if (linkid == DATALINK_ALL_LINKID) { 60610616SSebastien.Roy@Sun.COM (void) dladm_walk_datalink_id(i_iptun_down, handle, NULL, 60710616SSebastien.Roy@Sun.COM DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE, 60810616SSebastien.Roy@Sun.COM DLADM_OPT_ACTIVE); 60910616SSebastien.Roy@Sun.COM } else { 61010616SSebastien.Roy@Sun.COM (void) i_iptun_down(handle, linkid, &status); 61110616SSebastien.Roy@Sun.COM } 61210616SSebastien.Roy@Sun.COM return (status); 61310616SSebastien.Roy@Sun.COM } 61410616SSebastien.Roy@Sun.COM 61510616SSebastien.Roy@Sun.COM dladm_status_t 61610616SSebastien.Roy@Sun.COM dladm_iptun_set6to4relay(dladm_handle_t handle, struct in_addr *relay) 61710616SSebastien.Roy@Sun.COM { 61810616SSebastien.Roy@Sun.COM return (i_iptun_ioctl(handle, IPTUN_SET_6TO4RELAY, relay)); 61910616SSebastien.Roy@Sun.COM } 62010616SSebastien.Roy@Sun.COM 62110616SSebastien.Roy@Sun.COM dladm_status_t 62210616SSebastien.Roy@Sun.COM dladm_iptun_get6to4relay(dladm_handle_t handle, struct in_addr *relay) 62310616SSebastien.Roy@Sun.COM { 62410616SSebastien.Roy@Sun.COM return (i_iptun_ioctl(handle, IPTUN_GET_6TO4RELAY, relay)); 62510616SSebastien.Roy@Sun.COM } 626