765 lines
21 KiB
C
765 lines
21 KiB
C
/* if6Lib.c - IPv6 interface address library */
|
|
|
|
/* Copyright 2003 - 2005 Wind River Systems, Inc. */
|
|
#include "copyright_wrs.h"
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01p,29sep10,h_x Fix build and coverity warnings
|
|
01o,21jun10,h_x Fix WIND00217113
|
|
01n,21oct08,spw Use ipnet_suspend/resume_stack
|
|
01m,02jul08,spw Bug fixes
|
|
01l,26Nov07,brg Reinstated after rewriting 4 ipnet integration
|
|
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This library contains routines to configure IPv6 interface addresses.
|
|
Generally, each routine corresponds to one of the functions of the UNIX
|
|
command 'ifconfig'.
|
|
|
|
To use this feature, include the component INCLUDE_IF6LIB.
|
|
|
|
INCLUDE FILES: if6Lib.h
|
|
|
|
SEE ALSO: ifLib, ifconfig()
|
|
*/
|
|
|
|
#include <vxWorks.h>
|
|
#include <ioctl.h>
|
|
#include <ioLib.h>
|
|
#include <errnoLib.h>
|
|
#include <errno.h>
|
|
#include <types.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <net/if.h>
|
|
#include <net/if_var.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet6/in6_var.h>
|
|
#include <arpa/inet.h>
|
|
#include <inetLib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <net/utils/ifconfig.h>
|
|
#include <sockLib.h>
|
|
#include <if6Lib.h>
|
|
|
|
/* ipnet includes */
|
|
|
|
#include <ipcom_config.h>
|
|
#include <ipnet_config.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_vxworks.h>
|
|
#include <ipnet.h>
|
|
#include <ipnet_h.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipnet_ip6.h>
|
|
#include <ipnet_netif.h>
|
|
#include <ipnet_routesock.h>
|
|
|
|
|
|
LOCAL STATUS if6NameLoad(char *interfaceName, struct Ip_in6_aliasreq *ifr);
|
|
LOCAL STATUS if6AddrLoad(char *interfaceAddress, struct Ip_sockaddr_in6 *sin6);
|
|
LOCAL STATUS if6IoctlCall(int code, void *req);
|
|
LOCAL STATUS ifaddrGet(char *interfaceName,char *interfaceAddress,
|
|
struct Ip_in6_aliasreq *iareq);
|
|
#if 0
|
|
LOCAL void ifaddrToAliasreq(char *interfaceName, struct Ip_ifaddrs *ia,
|
|
struct in6_aliasreq *ifra);
|
|
|
|
#endif
|
|
/******************************************************************************
|
|
*
|
|
* ifLibInit - initialize if6Lib
|
|
*
|
|
* RETURNS: NONE
|
|
*
|
|
* NOMANUAL
|
|
*/
|
|
void if6LibInit
|
|
(
|
|
void
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6AddrGet - get an IPv6 address of a network interface
|
|
*
|
|
* This routine gets an IPv6 address of a specified network interface,
|
|
* and copies it to <interfaceAddress>, which must be large enough to
|
|
* contain INET6_ADDRSTRLEN (46) bytes.
|
|
*
|
|
* NOTE
|
|
* If the specified address is not found on the interface, this returns
|
|
* the first address, usually the link-local address.
|
|
*
|
|
* To get all addresses, use ifconfig(), ifShow(), or 'ioctl(IP_SIOCGIFCONF)'.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6AddrDelete()
|
|
*/
|
|
STATUS if6AddrGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress /* buffer for IPv6 address */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
char isAddr[INET6_ADDRSTRLEN];
|
|
int ret;
|
|
|
|
if (interfaceName == NULL || interfaceAddress == NULL)
|
|
return ERROR;
|
|
|
|
/* Did the user enter a valid address, or is it a buffer ? */
|
|
|
|
ret = ipcom_inet_pton(IP_AF_INET6, interfaceAddress, isAddr);
|
|
if (ret == -1)
|
|
return ERROR;
|
|
if (ret == 0)
|
|
{
|
|
/* not a valid address ... assume it's a buffer and mark it as such */
|
|
*interfaceAddress = '\0';
|
|
}
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress, &iareq)) == ERROR)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (inet_ntop(AF_INET6, &(iareq.ifra_addr.sin6_addr),
|
|
interfaceAddress, IP_INET6_ADDRSTRLEN) == NULL)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6AddrAdd - add an IPv6 address to a network interface
|
|
*
|
|
* This routine assigns an IPv6 address to a specified network interface.
|
|
* The address can be a host name or a standard IPv6 address format (e.g.,
|
|
* 3ffe:1::1111). If a host name is specified, it should already have been
|
|
* added to the host table with hostAdd().
|
|
*
|
|
* A <prefixLen> value of 0 is treated as equivalent to 128.
|
|
*
|
|
* See if6FlagSet() for flag values.
|
|
*
|
|
* The new address is created with a destination address of "::" (the
|
|
* unspecified address). To change the destination address, use
|
|
* if6DstAddrSet().
|
|
*
|
|
* The new address is created with Valid Lifetime and Preferred Lifetime
|
|
* values of infinity. To change the lifetime values, use if6LifetimeSet().
|
|
*
|
|
* RETURNS: OK, or ERROR if the address cannot be set.
|
|
*
|
|
* SEE ALSO: if6AddrDelete(), if6AddrGet(), if6DstAddrSet(), if6FlagSet(),
|
|
* if6LifetimeSet(), if6PrefixlenSet()
|
|
*/
|
|
STATUS if6AddrAdd
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address to assign to interface */
|
|
int prefixLen, /* prefix length */
|
|
int flags /* address flags */
|
|
)
|
|
{
|
|
|
|
struct Ip_in6_aliasreq ifareq;
|
|
ipcom_memset(&ifareq,0,sizeof(ifareq));
|
|
|
|
if (if6NameLoad(interfaceName, &ifareq) == ERROR)
|
|
return ERROR;
|
|
|
|
if (if6AddrLoad(interfaceAddress, &ifareq.ifra_addr) == ERROR)
|
|
/* XXX host lookup */
|
|
return ERROR;
|
|
|
|
ifareq.ifra_prefixmask.sin6_family = IP_AF_INET6;
|
|
ifareq.ifra_prefixmask.sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
ipnet_route_create_mask(&ifareq.ifra_prefixmask.sin6_addr, prefixLen);
|
|
|
|
ifareq.ifra_lifetime.ia6t_preferred = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
ifareq.ifra_lifetime.ia6t_expire = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
|
|
ifareq.ifra_flags = flags;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCAIFADDR_IN6, (void *) &ifareq));
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6AddrDelete - delete an IPv6 address from a network interface
|
|
*
|
|
* This routine deletes an IPv6 address from a specified network interface.
|
|
* The address can be a host name or a standard IPv6 address format (e.g.,
|
|
* 3ffe:1::1111). If a host name is specified, it should already have been
|
|
* added to the host table with hostAdd().
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6AddrGet()
|
|
*/
|
|
STATUS if6AddrDelete
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress /* IPv6 address to delete from interface */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq ifareq;
|
|
ipcom_memset(&ifareq,0,sizeof(ifareq));
|
|
|
|
if (if6NameLoad(interfaceName, &ifareq) == ERROR)
|
|
return ERROR;
|
|
|
|
if (if6AddrLoad(interfaceAddress, &ifareq.ifra_addr) == ERROR)
|
|
/* XXX host lookup */
|
|
return ERROR;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCDIFADDR_IN6, (void *) &ifareq));
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6DstAddrGet - get the IPv6 address of a point-to-point peer
|
|
*
|
|
* This routine gets the IPv6 address of a node connected to the opposite
|
|
* end of a point-to-point network connection. The address is copied to the
|
|
* buffer <dstAddress>, which must be large enough to contain
|
|
* INET6_ADDRSTRLEN (46) bytes.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6DstAddrSet()
|
|
*/
|
|
STATUS if6DstAddrGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
char *dstAddress /* buffer for destination address */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if (if6NameLoad(interfaceName, &iareq) == ERROR)
|
|
return ERROR;
|
|
|
|
if ((if6IoctlCall((int)IP_SIOCGIFDSTADDR_IN6,(void*)&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
if (ipcom_inet_ntop(IP_AF_INET6, &(iareq.ifra_addr.sin6_addr),
|
|
dstAddress, IP_INET6_ADDRSTRLEN) == NULL)
|
|
return ERROR;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6DstAddrSet - set the IPv6 address of a point-to-point peer
|
|
*
|
|
* This routine assigns the IPv6 address of a node connected to the
|
|
* opposite end of a point-to-point network connection, such as a PPP
|
|
* connection.
|
|
*
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6DstAddrGet()
|
|
*/
|
|
STATUS if6DstAddrSet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
char *dstAddress /* buffer for destination address */
|
|
)
|
|
{
|
|
|
|
return ERROR;
|
|
#if 0
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
/* Warning! in6_alias req and Ip_in6_aliasreq should be the same
|
|
ipcom_bsdsocket.h assumption
|
|
*/
|
|
|
|
if (if6AddrLoad(dstAddress, &iareq.ifra_dstaddr) == ERROR)
|
|
return ERROR;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCAIFADDR_IN6, (void *) &iareq));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6PrefixlenGet - get the prefix length of an IPv6 address
|
|
*
|
|
* This routine gets the prefix length of an IPv6 address, and copies it to
|
|
* <prefixLen>.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6PrefixlenSet()
|
|
*/
|
|
STATUS if6PrefixlenGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
int *prefixLen /* prefix length returned here */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
*prefixLen = ipcom_sockaddr_to_prefixlen((struct Ip_sockaddr *) &iareq.ifra_prefixmask);
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6PrefixlenSet - set the prefix length of an IPv6 address
|
|
*
|
|
* This routine sets the prefix length of an IPv6 address.
|
|
*
|
|
* A <prefixLen> value of 0 is treated as equivalent to 128.
|
|
*
|
|
* NOTE
|
|
* The kernel does not allow the prefix length to be changed on an existing
|
|
* address. Therefore, this routine deletes the old address, and adds a new
|
|
* address with the new prefix length.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6PrefixlenGet()
|
|
*/
|
|
STATUS if6PrefixlenSet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
int prefixLen /* prefix length */
|
|
)
|
|
{
|
|
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
iareq.ifra_prefixmask.sin6_family = IP_AF_INET6;
|
|
iareq.ifra_prefixmask.sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
ipnet_route_create_mask(&iareq.ifra_prefixmask.sin6_addr, prefixLen);
|
|
|
|
/* AddrGet returns absolute value */
|
|
iareq.ifra_lifetime.ia6t_preferred = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
iareq.ifra_lifetime.ia6t_expire = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
|
|
if (if6AddrDelete(interfaceName, interfaceAddress) == ERROR)
|
|
return ERROR;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCAIFADDR_IN6, (void *) &iareq));
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6FlagGet - get the flags for an IPv6 interface address
|
|
*
|
|
* This routine gets the flags for a specified IPv6 address, and copies them
|
|
* to <flags>.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6FlagSet()
|
|
*/
|
|
STATUS if6FlagGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
int *flags /* network flags returned here */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
*flags = iareq.ifra_flags;
|
|
|
|
return OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6FlagSet - set the flags for an IPv6 address
|
|
*
|
|
* This routine set the flags for a specified IPv6 address.
|
|
* Any combination of the following flags can be specified:
|
|
* \is
|
|
* \i IP_IN6_IFF_TEMPORARY (0x01)
|
|
* Temporary address.
|
|
* \i IP_IN6_IFF_TENTATIVE (0x02)
|
|
* Do DAD before assigning this address.
|
|
* \i IP_IN6_IFF_HOMEADDRESS (0x04)
|
|
* Home address
|
|
* \i IP_IN6_IFF_AUTONOMOUS (0x20)
|
|
* Created based on prefix adv.
|
|
* \i IP_IN6_IFF_ANYCAST (0x40)
|
|
* This is an anycast address.
|
|
* \ie
|
|
*
|
|
* NOTE
|
|
* The kernel does not allow the flags to be changed on an existing
|
|
* address. Therefore, this routine deletes the old address, and adds a new
|
|
* address with the new flags.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6FlagGet()
|
|
*/
|
|
STATUS if6FlagSet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
int flags /* address flags */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
|
|
iareq.ifra_flags = flags;
|
|
|
|
if (if6AddrDelete(interfaceName, interfaceAddress) == ERROR)
|
|
return ERROR;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCAIFADDR_IN6, (void *) &iareq));
|
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6FlagChange - change the flags for an IPv6 address
|
|
*
|
|
* This routine changes the flags for the specified network interfaces. If
|
|
* the parameter <on> is TRUE, the specified flags are turned on; otherwise,
|
|
* they are turned off.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6FlagGet(), if6FlagSet()
|
|
*/
|
|
STATUS if6FlagChange
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
int flags, /* the flags to be changed */
|
|
BOOL on /* TRUE=turn on, FALSE=turn off */
|
|
)
|
|
{
|
|
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
if (on)
|
|
iareq.ifra_flags |= flags;
|
|
else
|
|
iareq.ifra_flags &= ~flags;
|
|
|
|
return (if6FlagSet(interfaceName,interfaceAddress,iareq.ifra_flags));
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6LifetimeGet - get the lifetime of an IPv6 address
|
|
*
|
|
* This routine gets the "absolute" time corressponding to the Valid
|
|
* Lifetime and Preferred Lifetime values for an IPv6 address.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6LifetimeSet()
|
|
*/
|
|
STATUS if6LifetimeGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
Ip_time_t *vltime, /* valid lifetime */
|
|
Ip_time_t *pltime /* preferred lifetime */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
*vltime = iareq.ifra_lifetime.ia6t_expire;
|
|
*pltime = iareq.ifra_lifetime.ia6t_preferred;
|
|
|
|
return OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6LifetimeSet - set the lifetime of an IPv6 address
|
|
*
|
|
* This routine sets the Valid Lifetime and Preferred Lifetime values
|
|
* in seconds for an IPv6 address.
|
|
*
|
|
* A lifetime value of all ones (0xffffffff) is treated as infinity.
|
|
*
|
|
* RETURNS: OK or ERROR.
|
|
*
|
|
* SEE ALSO: if6AddrAdd(), if6LifetimeGet()
|
|
*/
|
|
STATUS if6LifetimeSet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* IPv6 address on interface */
|
|
Ip_time_t vltime, /* valid lifetime */
|
|
Ip_time_t pltime /* preferred lifetime */
|
|
)
|
|
{
|
|
struct Ip_in6_aliasreq iareq;
|
|
|
|
if ((ifaddrGet(interfaceName, interfaceAddress,&iareq)) == ERROR)
|
|
return ERROR;
|
|
|
|
iareq.ifra_lifetime.ia6t_expire = vltime;
|
|
iareq.ifra_lifetime.ia6t_preferred = pltime;
|
|
|
|
return (if6IoctlCall((int)IP_SIOCAIFADDR_IN6, (void *) &iareq));
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* ifaddrGet - look up an Ip_ifaddrs struct for an IPv6 interface address
|
|
*
|
|
* RETURNS: pointer or NULL
|
|
*/
|
|
LOCAL STATUS ifaddrGet
|
|
(
|
|
char *interfaceName, /* name of interface */
|
|
char *interfaceAddress, /* string representation of address */
|
|
struct Ip_in6_aliasreq *ifareq /* interface aliasreq */
|
|
)
|
|
{
|
|
|
|
struct Ip_in6_addr sin6_addr;
|
|
Ipnet_netif *netif;
|
|
Ipnet_ip6_addr_entry *address;
|
|
STATUS err=OK;
|
|
void *handle = IP_NULL;
|
|
|
|
if (interfaceName == NULL) {
|
|
err = ERROR;
|
|
goto out;
|
|
}
|
|
|
|
ipcom_strncpy(ifareq->ifra_name, interfaceName, sizeof(char)*IP_IFNAMSIZ);
|
|
|
|
if(interfaceAddress == NULL || *interfaceAddress == '\0')
|
|
{
|
|
/* Return 1 address from interface */
|
|
|
|
handle = ipnet_suspend_stack();
|
|
|
|
if (handle == IP_NULL)
|
|
{
|
|
err = ERROR;
|
|
goto out;
|
|
}
|
|
|
|
netif = ipnet_if_nametonetif((Ip_u16)ipcom_proc_vr_get(), ifareq->ifra_name);
|
|
if (netif == IP_NULL) {
|
|
ipnet_resume_stack(handle);
|
|
err = ERROR;
|
|
goto out;
|
|
}
|
|
|
|
address = (Ipnet_ip6_addr_entry *)netif->inet6_addr_list;
|
|
|
|
if(address == IP_NULL)
|
|
{
|
|
ipnet_resume_stack(handle);
|
|
err=ERROR;
|
|
goto out;
|
|
}
|
|
|
|
ipcom_memcpy(&ifareq->ifra_addr.sin6_addr,&address->addr,sizeof(struct Ip_in6_addr));
|
|
ifareq->ifra_addr.sin6_family=IP_AF_INET6;
|
|
ifareq->ifra_addr.sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
ifareq->ifra_flags=0;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_TEMPORARY))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_TEMPORARY;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_TENTATIVE))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_TENTATIVE;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_HOMEADDRESS))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_HOMEADDRESS;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_AUTONOMOUS))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_AUTONOMOUS;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_ANYCAST))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_ANYCAST;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_DEPRECATED))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_DEPRECATED;
|
|
if (IP_BIT_ISSET(address->flags, IPNET_IP6_ADDR_FLAG_AUTOMATIC))
|
|
ifareq->ifra_flags |= IP_IN6_IFF_AUTOMATIC;
|
|
ifareq->ifra_lifetime.ia6t_expire = address->expires_sec;
|
|
ifareq->ifra_lifetime.ia6t_preferred = address->preferred_sec;
|
|
ifareq->ifra_lifetime.ia6t_pltime = 0;
|
|
ifareq->ifra_lifetime.ia6t_vltime = 0;
|
|
ifareq->ifra_prefixmask.sin6_family = IP_AF_INET6;
|
|
ipcom_memset(&ifareq->ifra_prefixmask, 0, sizeof(ifareq->ifra_prefixmask));
|
|
ipnet_route_create_mask(&ifareq->ifra_prefixmask.sin6_addr, (int)(address->prefixlen));
|
|
|
|
ipnet_resume_stack(handle);
|
|
err=OK;
|
|
goto out;
|
|
|
|
|
|
}
|
|
|
|
if (ipcom_inet_pton(IP_AF_INET6, interfaceAddress,(void *) &sin6_addr) <= 0)
|
|
{
|
|
err=ERROR;
|
|
goto out;
|
|
|
|
}
|
|
|
|
ifareq->ifra_addr.sin6_family=IP_AF_INET6;
|
|
ifareq->ifra_addr.sin6_len=sizeof(struct Ip_sockaddr_in6);
|
|
ipcom_memcpy(&ifareq->ifra_addr.sin6_addr, &sin6_addr, sizeof(struct Ip_in6_addr));
|
|
|
|
ipcom_memset(&ifareq->ifra_prefixmask, 0, sizeof(ifareq->ifra_prefixmask));
|
|
|
|
/* Get address information */
|
|
if (if6IoctlCall((int)IP_SIOCXGIFADDR_IN6, (void*)ifareq) != OK)
|
|
{
|
|
err=ERROR;
|
|
goto out;
|
|
}
|
|
|
|
/* Needed for prefixLenxx functions as the ioctl call doesnt set
|
|
* the addr family and size */
|
|
|
|
ifareq->ifra_prefixmask.sin6_family = IP_AF_INET6;
|
|
ifareq->ifra_prefixmask.sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
|
|
out:
|
|
return err;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6NameLoad - load an interface name into a request struct
|
|
*
|
|
* RETURNS: OK or ERROR
|
|
*/
|
|
LOCAL STATUS if6NameLoad
|
|
(
|
|
char *interfaceName, /* name of the network interface, i.e. ei0 */
|
|
struct Ip_in6_aliasreq *ifr /* request struct */
|
|
)
|
|
{
|
|
/* in6_ifreq.ifr_name and in6_aliasreq.ifra_name are equal-size
|
|
* buffers at the beginnings of their respective structs
|
|
*/
|
|
return (strncpy (ifr->ifra_name, interfaceName, sizeof(ifr->ifra_name))
|
|
? OK : ERROR);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6AddrLoad - load an interface address into a request struct
|
|
*
|
|
* RETURNS: OK or ERROR
|
|
*/
|
|
LOCAL STATUS if6AddrLoad
|
|
(
|
|
char *interfaceAddress, /* string representation of address */
|
|
struct Ip_sockaddr_in6 *sin6 /* binary representation of address */
|
|
)
|
|
{
|
|
if (ipcom_inet_pton(IP_AF_INET6, interfaceAddress, (void *) &sin6->sin6_addr) <= 0)
|
|
return ERROR;
|
|
|
|
sin6->sin6_len = sizeof(*sin6);
|
|
sin6->sin6_family = AF_INET6;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* if6IoctlCall - make ioctl call to socket layer
|
|
*
|
|
* RETURNS: OK or ERROR
|
|
*/
|
|
LOCAL STATUS if6IoctlCall
|
|
(
|
|
int code, /* ioctl code */
|
|
void *req /* pointer to the interface ioctl request */
|
|
)
|
|
{
|
|
Ip_fd sock;
|
|
Ip_s32 status;
|
|
|
|
if ((sock = ipcom_socket (IP_AF_INET6, IP_SOCK_RAW, 0)) == IP_SOCKERR)
|
|
return (ERROR);
|
|
|
|
status = ipcom_socketioctl(sock, (unsigned long)code, req);
|
|
(void) ipcom_socketclose(sock);
|
|
|
|
if (status < 0)
|
|
{
|
|
return (ERROR);
|
|
}
|
|
|
|
return (OK);
|
|
}
|
|
|
|
|
|
|