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