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

491 lines
17 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip4_if.c,v $ $Revision: 1.24.16.2 $
* $Source: /home/interpeak/CVSRoot/ipmip4/src/ipmip4_if.c,v $
* $Author: jsheng $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip4_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_drv_eth_filter.h>
#include <ipcom_err.h>
#include <ipcom_hash.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_netif.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_netlink.h>
#include <private/ipmip_log.h>
#include "ipmip4_h.h"
#include <private/ipmip4_util.h>
#include <private/ipmip4_if.h>
#include <private/ipmip4_pkt.h>
#include <private/ipmip4_pktbuf.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip4_if_destroy_tunnel
*===========================================================================
* Description: Destroy a particular tunnel.
* Parameters: iff - The tunnel to destroy.
* Returns:
*/
IP_STATIC void
ipmip4_if_destroy_tunnel(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip4_if_t *iff)
{
struct Ip_ifreq ifreq;
int i;
/* No tunnel, don't bother */
if (iff->ipmip.ifindex == 0)
return;
for (i = 0; i < 4; i++)
{
/* Do down & destroy */
ipmip_if_clear_flags(&ctx->ipmip, proc, &iff->ipmip, IP_IFF_UP);
if (ipmip_if_ioctl(&ctx->ipmip, proc, &iff->ipmip, IP_SIOCIFDESTROY, &ifreq) < 0)
{
IPCOM_LOG3(ERR, "ipcom_socketioctl(%s, IP_SIOCIFDESTROY) failed: %s [%d]",
iff->ipmip.ifname,
ipcom_strerror(ipcom_errno),
ipcom_errno);
ipcom_sleep(1);
}
else
{
IPCOM_LOG1(DEBUG, "tunnel interface '%s' destroyed",
iff->ipmip.ifname);
break;
}
}
/* Reset index */
iff->ipmip.ifindex = 0;
}
/*
*===========================================================================
* ipmip4_if_free
*===========================================================================
* Description: Destroy and free the interface specific data.
* Parameters: ctx - Context
* proc - Process
* iff - the interface to destroy
* Returns:
*/
IP_STATIC void
ipmip4_if_free(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip4_if_t *iff)
{
/* Invoke cleanup functionality */
if (iff->cleanup)
(*iff->cleanup) (&ctx->ipmip, proc, &iff->ipmip);
/* Destroy this particular tunnel */
if (iff->ipmip.type == IPMIP_IF_TYPE_TUNNEL)
ipmip4_if_destroy_tunnel(ctx, proc, iff);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip4_if_alloc
*===========================================================================
* Description: Allocate and initialize the interface structure
* Parameters: ctx - Context
* proc - Process
* ifsize - the size of the interface structure
* ifname - The interface name
* ifindex - The interface index.
* type - Type of interface
* identity- The interface identity.
* cleanup - Function to be invoked prior to free.
* Returns: The interface structure on success.
*/
IP_GLOBAL Ipmip4_if_t *
ipmip4_if_alloc(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t ifsize,
const char *ifname,
Ip_u32 ifindex,
Ip_u8 type,
Ip_u8 identity,
Ipmip_if_cleanup_t cleanup)
{
Ipmip4_if_t *iff = (Ipmip4_if_t *)ipmip_if_alloc(&ctx->ipmip,
proc,
ifsize,
ifname,
ifindex,
type,
identity,
(Ipmip_if_cleanup_t)ipmip4_if_free);
if (iff == IP_NULL)
return IP_NULL;
ipcom_list_init(&iff->pktbufs);
iff->cleanup = cleanup;
return iff;
}
/*
*===========================================================================
* ipmipfa_if_alloc_tunnel
*===========================================================================
* Description: Create a specific tunnel for the provided interface
* Parameters: ctx - Context
* proc - Process
* ifsize - Total size of the interface structure
* ifname - Wanted ifname
* local - The local endpoint
* local_port - Base port for NAT_T setup
* remote - Remote endpoint
* identity - The identity of the tunnel
* tunnel_type - Tunnel type
* reorder - Enable reordering if supported by interface
* cleanup - Function to be invoked prior to free.
* Returns: The interface structure on success.
*
*/
IP_GLOBAL Ipmip4_if_t *
ipmip4_if_alloc_tunnel(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ip_size_t ifsize,
char *ifname,
Ip_u32 local,
Ip_u16 local_port,
Ip_u32 remote,
Ip_u8 identity,
Ip_u8 tunnel_type,
Ip_bool reorder,
Ipmip_if_cleanup_t cleanup)
{
struct Ip_ifreq ifreq;
struct Ip_ifaliasreq alias;
struct Ip_ip_tunnel_param tun;
struct Ip_sockaddr_in *inaddr;
Ip_u16 flags;
Ipmip4_if_t *iff;
/* Allocate the structure */
iff = ipmip4_if_alloc(ctx, proc, ifsize, ifname, 0, IPMIP_IF_TYPE_TUNNEL, identity, cleanup);
if (iff == IP_NULL)
return IP_NULL;
/* Try create the interface */
if (ipmip_if_ioctl(&ctx->ipmip, proc, &iff->ipmip, IP_SIOCIFCREATE, &ifreq) < 0)
{
IPCOM_LOG3(ERR, "ipcom_socketioctl(%s, IP_SIOCIFCREATE) failed : %s [%d]",
iff->ipmip.ifname,
ipcom_strerror(ipcom_errno),
ipcom_errno);
goto destroy;
}
/* May have been modified */
ipcom_strncpy(iff->ipmip.ifname, ifreq.ifr_name, IP_IFNAMSIZ);
/* Store the index */
iff->ipmip.ifindex = ipcom_if_nametoindex(iff->ipmip.ifname);
iff->ipmip.tunnel_type = tunnel_type;
/* Change tunnel */
ipcom_memset(&tun, 0, sizeof(tun));
if((IP_IFNAMSIZ - 1) < strlen(iff->ipmip.ifname))
{
goto destroy;
}
ipcom_strcpy(tun.ifr_name, iff->ipmip.ifname);
tun.local_addr.sin.sin_family = IP_AF_INET;
tun.local_addr.sin.sin_addr.s_addr = local;
IPCOM_SA_LEN_SET(&tun.local_addr.sin, sizeof(struct Ip_sockaddr_in));
/* Prepare the tunnel for NAT-T */
tun.local_addr.sin.sin_port = local_port;
tun.remote_addr.sin.sin_family = IP_AF_INET;
tun.remote_addr.sin.sin_addr.s_addr = remote;
IPCOM_SA_LEN_SET(&tun.remote_addr.sin, sizeof(struct Ip_sockaddr_in));
tun.ttl = 64;
/* Set tunnel interface address */
if (local)
{
ipcom_memset(&alias, 0, sizeof(alias));
ipcom_strcpy(alias.ifra_name, ifreq.ifr_name);
inaddr = (struct Ip_sockaddr_in *)&alias.ifra_addr;
inaddr->sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(inaddr, sizeof(struct Ip_sockaddr_in));
inaddr->sin_addr.s_addr = local;
inaddr = (struct Ip_sockaddr_in *)&alias.ifra_mask;
inaddr->sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(inaddr, sizeof(struct Ip_sockaddr_in));
inaddr->sin_addr.s_addr = 0xffffffff;
/* Assign the CoA address */
if (ipmip_netlink_inX_addr(&ctx->ipmip, proc, IP_AF_INET, IP_RTM_NEWADDR, iff->ipmip.ifindex, &local, 32, 0, 0) < 0)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->ipmip,
proc,
"Unable to assign address to tunnel interface %s",
iff->ipmip.ifname));
goto destroy;
}
}
/**/
flags = IP_IFF_UP;
if (tunnel_type == IPMIP_TUNNELTYPE_MINENC)
IP_BIT_SET(flags, IP_IFF_LINK0);
if (tunnel_type == IPMIP_TUNNELTYPE_GRE && reorder)
IP_BIT_SET(flags, IP_IFF_LINK1);
if (ipmip_if_set_flags(&ctx->ipmip, proc, &iff->ipmip, flags) < 0)
{
IPCOM_LOG3(ERR, "ipcom_socketioctl(%s, IP_SIOCSIFFLAGS) failed: %s [%d]",
iff->ipmip.ifname,
ipcom_strerror(ipcom_errno),
ipcom_errno);
goto destroy;
}
/* Set endpoints; will update minenc if set as well. */
if (ipmip_util_ioctl(&ctx->ipmip, proc, IP_SIOCCHGTUNNEL, &tun) < 0)
{
IPCOM_LOG3(ERR, "ipcom_socketioctl(%s, IP_SIOCCHGTUNNEL) failed: %s [%d]",
iff->ipmip.ifname,
ipcom_strerror(ipcom_errno),
ipcom_errno);
goto destroy;
}
return iff;
destroy:
ipmip_if_free(&ctx->ipmip, proc, &iff->ipmip);
return IP_NULL;
}
/*
*===========================================================================
* ipmip4_if_get_primary_address
*===========================================================================
* Description: Get the current primary address of the interface.
* Parameters: iff - Interface
* Returns: address on success; IP_INADDR_NONE on failure.
*
*/
IP_GLOBAL Ip_u32
ipmip4_if_get_primary_address(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ipmip4_if_t *iff)
{
Ipmip_buffer_t reply;
int ret;
Ip_u32 addr = IP_INADDR_NONE;
ipmip_buffer_init(&reply);
if ((ret = ipmip_netlink_inX_addr_dump(&ctx->ipmip, proc, IP_AF_INET, &reply)) < 0)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->ipmip,
proc,
"Unable to dump INET addresses error value %d", -ret));
}
else
{
struct Ip_nlmsghdr *nlh = IPMIP_BUFFER_PTR(&reply);
Ip_size_t nlh_size = IPMIP_BUFFER_SIZE(&reply);
/* */
while (IP_NLMSG_OK(nlh, nlh_size))
{
/**/
if (nlh->nlmsg_type == IP_RTM_NEWADDR)
{
struct Ip_ifaddrmsg *ifa = IP_NLMSG_DATA(nlh);
struct Ip_rtattr *ifap[IP_IFA_MAX + 1];
/* Resolve this entry; I want the prefix length and the address */
if (ifa->ifa_index == (Ip_s32)iff->ipmip.ifindex)
{
/* Parse */
ipmip_netlink_nlmsghdr_rta_parse(IP_IFA_MAX + 1,
IP_IFA_RTA(ifa),
IP_IFA_PAYLOAD(nlh),
ifap);
/* Found one */
if (ifap[IP_IFA_LOCAL])
{
if (ifa->ifa_family == IP_AF_INET)
{
addr = IP_GET_32ON8(IP_RTA_DATA(ifap[IP_IFA_LOCAL]));
break;
}
}
}
}
/**/
nlh = IP_NLMSG_NEXT(nlh, nlh_size);
}
}
/**/
ipmip_buffer_release(&reply);
return addr;
}
/*
*===========================================================================
* ipmip4_if_findbyaddr
*===========================================================================
* Description: Locate an interface in our configuration based on address.
* Parameters: iflist - The list of interfaces.
* addr - The interface address
* Returns: The interface pointer if it exists, IP_NULL otherwise.
*/
IP_GLOBAL Ipmip4_if_t *
ipmip4_if_findbyaddr(Ipcom_list *iflist,
Ip_u32 addr)
{
Ipmip4_if_t *iff;
for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->ipmip.next))
{
if (iff->ifaddr == addr)
return iff;
}
return IP_NULL;
}
/*
*===========================================================================
* ipmip4_if_findbypktinfo
*===========================================================================
* Description: Locate an interface in our configuration based on address.
* Parameters: iflist - The list of interfaces
* pktinfo - The interface info
* Returns: The interface pointer if it exists, IP_NULL otherwise.
*/
IP_GLOBAL Ipmip4_if_t *
ipmip4_if_findbypktinfo(Ipcom_list *iflist,
Ipmip_pktbuf_pktinfo_t *pktinfo)
{
Ipmip4_if_t *iff;
if ((iff = ipmip4_if_findbyaddr(iflist, pktinfo->dst.sin.sin_addr.s_addr)) == IP_NULL)
iff = (Ipmip4_if_t *)ipmip_if_findbyindex(iflist, pktinfo->ifindex);
return iff;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/