Files
m241Neelima/components/ip_net2-6.9/vxcompat/src/if6Lib.c
T
2026-07-30 11:19:44 +05:30

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);
}