/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stropts.h>
#include <string.h>
#include <netdb.h>
#include <libdlpi.h>
#include <libdladm_impl.h>
#include <libdllink.h>
#include <libdliptun.h>
/*
* IP Tunneling Administration Library.
* This library is used by dladm(1M) and to configure IP tunnel links.
*/
/*
* If IPTUN_CREATE and IPTUN_MODIFY include IPsec policy and IPsec hasn't
* loaded yet, the ioctls may return EAGAIN. We try the ioctl
* IPTUN_IOCTL_ATTEMPT_LIMIT times and wait IPTUN_IOCTL_ATTEMPT_INTERVAL
* microseconds between attempts.
*/
{
if (attempt != 0)
(void) usleep(IPTUN_IOCTL_ATTEMPT_INTERVAL);
if (status != DLADM_STATUS_TRYAGAIN)
break;
}
return (status);
}
/*
* Given tunnel parameters as supplied by a library consumer, fill in kernel
* parameters to be passed down to the iptun control device.
*/
static dladm_status_t
{
}
if (iptuntype == IPTUN_TYPE_UNKNOWN) {
/*
* We need to get the type of this existing tunnel in
* IP address.
*/
if (status != DLADM_STATUS_OK)
return (status);
}
switch (iptuntype) {
case IPTUN_TYPE_IPV4:
case IPTUN_TYPE_6TO4:
break;
case IPTUN_TYPE_IPV6:
break;
}
}
0)
return (DLADM_STATUS_BADIPTUNLADDR);
return (DLADM_STATUS_BADIPTUNLADDR);
}
ai->ai_addrlen);
}
0)
return (DLADM_STATUS_BADIPTUNRADDR);
return (DLADM_STATUS_BADIPTUNRADDR);
}
ai->ai_addrlen);
}
}
return (DLADM_STATUS_OK);
}
/*
* The inverse of i_iptun_kparams(). Given kernel tunnel parameters as
* returned from an IPTUN_INFO ioctl, fill in tunnel parameters.
*/
static dladm_status_t
{
}
sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
if (getnameinfo((const struct sockaddr *)
NI_NUMERICHOST) != 0) {
return (DLADM_STATUS_BADIPTUNLADDR);
}
}
sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6);
if (getnameinfo((const struct sockaddr *)
NI_NUMERICHOST) != 0) {
return (DLADM_STATUS_BADIPTUNRADDR);
}
}
}
return (DLADM_STATUS_OK);
}
{
if (status == DLADM_STATUS_OK)
return (status);
}
/*
* Read tunnel parameters from persistent storage. Note that the tunnel type
* is the only thing which must always be in the configuratioh. All other
* parameters (currently the source and destination addresses) may or may not
* have been configured, and therefore may not have been set.
*/
static dladm_status_t
{
/* First, make sure that this is an IP tunnel. */
return (status);
if (class != DATALINK_CLASS_IPTUN)
return (DLADM_STATUS_LINKINVAL);
&conf)) != DLADM_STATUS_OK) {
return (status);
}
params->iptun_param_flags = 0;
sizeof (temp))) != DLADM_STATUS_OK)
goto done;
done:
return (status);
}
static dladm_status_t
{
/* The tunnel type is required for creation. */
return (DLADM_STATUS_IPTUNTYPEREQD);
return (status);
}
static dladm_status_t
{
if (status != DLADM_STATUS_OK)
return (status);
if (status != DLADM_STATUS_OK)
goto done;
if (status != DLADM_STATUS_OK)
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
}
done:
return (status);
}
static dladm_status_t
{
if (status != DLADM_STATUS_OK)
return (status);
return (DLADM_STATUS_OK);
}
static dladm_status_t
{
return (status);
}
static dladm_status_t
{
/*
* The only parameters that can be modified persistently are the local
* and remote addresses.
*/
return (DLADM_STATUS_BADARG);
if (status != DLADM_STATUS_OK)
return (status);
if (status != DLADM_STATUS_OK)
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
}
done:
return (status);
}
{
return (DLADM_STATUS_IPTUNTYPEREQD);
switch (params->iptun_param_type) {
case IPTUN_TYPE_IPV4:
break;
case IPTUN_TYPE_IPV6:
break;
case IPTUN_TYPE_6TO4:
break;
default:
return (DLADM_STATUS_IPTUNTYPE);
}
if (status != DLADM_STATUS_OK)
return (status);
if (flags & DLADM_OPT_PERSIST) {
if (status != DLADM_STATUS_OK)
goto done;
}
if (flags & DLADM_OPT_ACTIVE) {
(void) dladm_remove_conf(handle,
}
}
done:
if (status != DLADM_STATUS_OK) {
(void) dladm_destroy_datalink_id(handle,
}
return (status);
}
{
/* First, make sure that this is an IP tunnel. */
NULL, 0)) != DLADM_STATUS_OK)
return (status);
if (class != DATALINK_CLASS_IPTUN)
return (DLADM_STATUS_LINKINVAL);
if (flags & DLADM_OPT_ACTIVE) {
/*
* Note that if i_iptun_delete_sys() fails with
* DLADM_STATUS_NOTFOUND and the caller also wishes to delete
* the persistent configuration, we still fall through to the
* DLADM_OPT_PERSIST case in case the tunnel only exists
* persistently.
*/
if (status != DLADM_STATUS_OK &&
(status != DLADM_STATUS_NOTFOUND ||
!(flags & DLADM_OPT_PERSIST)))
return (status);
}
if (flags & DLADM_OPT_PERSIST) {
}
return (DLADM_STATUS_OK);
}
{
/*
* We can only modify the tunnel source, tunnel destination, or IPsec
* policy.
*/
if (!(params->iptun_param_flags &
return (DLADM_STATUS_BADARG);
if (flags & DLADM_OPT_PERSIST) {
/*
* Before we change the database, save the old configuration
* so that we can revert back if an error occurs.
*/
if (status != DLADM_STATUS_OK)
return (status);
/* we'll only need to revert the parameters being modified */
if (status != DLADM_STATUS_OK)
return (status);
}
if (flags & DLADM_OPT_ACTIVE) {
}
}
return (status);
}
{
if (flags & DLADM_OPT_ACTIVE)
else if (flags & DLADM_OPT_PERSIST)
else
return (DLADM_STATUS_BADARG);
}
static int
{
if (status != DLADM_STATUS_OK)
goto done;
done:
}
return (DLADM_WALK_CONTINUE);
}
static int
{
return (DLADM_WALK_CONTINUE);
}
/* ARGSUSED */
{
if (linkid == DATALINK_ALL_LINKID) {
} else {
}
return (status);
}
{
if (linkid == DATALINK_ALL_LINKID) {
} else {
}
return (status);
}
{
}
{
}