473 lines
15 KiB
C
473 lines
15 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_if.c,v $ $Revision: 1.7.16.4 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_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 <ipmip_config.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysvar.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_context.h>
|
|
#include <private/ipmip_if.h>
|
|
#include <private/ipmip_util.h>
|
|
#include <private/ipmip_buffer.h>
|
|
#include <private/ipmip_netlink.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_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.
|
|
* cleanup - Function to be invoked prior to free.
|
|
* Returns: The interface structure on success.
|
|
*/
|
|
IP_GLOBAL Ipmip_if_t *
|
|
ipmip_if_alloc(Ipmip_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)
|
|
{
|
|
Ipmip_if_t *iff = ipcom_calloc(1, ifsize);
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (iff == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
iff->ifindex = ifindex;
|
|
if (ifname)
|
|
ipcom_strncpy(iff->ifname, ifname, IP_IFNAMSIZ);
|
|
|
|
iff->type = type;
|
|
iff->identity = identity;
|
|
|
|
iff->lladdr = IP_NULL;
|
|
iff->cleanup = cleanup;
|
|
return iff;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_free
|
|
*===========================================================================
|
|
* Description: Destroy and free the interface specific data.
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* iff - the interface to destroy
|
|
* Returns:
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip_if_free(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff)
|
|
{
|
|
/* If we're in any list; remove us */
|
|
if (iff->next.head != IP_NULL)
|
|
ipcom_list_remove(&iff->next);
|
|
|
|
/* Invoke cleanup functionality */
|
|
if (iff->cleanup)
|
|
(*iff->cleanup) (ctx, proc, iff);
|
|
|
|
if (iff->lladdr)
|
|
{
|
|
ipcom_free(iff->lladdr);
|
|
iff->lladdr = IP_NULL;
|
|
}
|
|
|
|
ipcom_free(iff);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip4_if_ioctl
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmip_if_ioctl(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff,
|
|
unsigned long ioctl,
|
|
struct Ip_ifreq *ifreq)
|
|
{
|
|
if((IP_IFNAMSIZ - 1) < strlen(iff->ifname))
|
|
{
|
|
return -1;
|
|
}
|
|
ipcom_strcpy(ifreq->ifr_name, iff->ifname);
|
|
return ipmip_util_ioctl(ctx, proc, ioctl, ifreq);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_get_flags
|
|
*===========================================================================
|
|
* Description: Get the current interface flags.
|
|
* Parameters: ctx - The context
|
|
* proc - The process.
|
|
* iff - The interface
|
|
* flags - Where to store the flags.
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_if_get_flags(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff,
|
|
Ip_u16 *flags)
|
|
{
|
|
struct Ip_ifreq ifreq;
|
|
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
|
|
return IP_FALSE;
|
|
|
|
*flags = ifreq.ifr_ifru.ifru_flags;
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_set_flags
|
|
*===========================================================================
|
|
* Description: Set the current interface flags.
|
|
* Parameters: ctx - The context
|
|
* proc - The process
|
|
* iff - The interface
|
|
* flags - The flags to set
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_if_set_flags(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff,
|
|
Ip_u16 flags)
|
|
{
|
|
struct Ip_ifreq ifreq;
|
|
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
|
|
return IP_FALSE;
|
|
|
|
IP_BIT_SET(ifreq.ifr_ifru.ifru_flags, flags);
|
|
|
|
if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0)
|
|
return IP_FALSE;
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_clear_flags
|
|
*===========================================================================
|
|
* Description: Clear the current interface flags.
|
|
* Parameters: iff - The interface
|
|
* flags - The flags to clear
|
|
* Returns: IP_TRUE on success
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_if_clear_flags(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff,
|
|
Ip_u16 flags)
|
|
{
|
|
struct Ip_ifreq ifreq;
|
|
|
|
|
|
if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0)
|
|
return IP_FALSE;
|
|
|
|
IP_BIT_CLR(ifreq.ifr_ifru.ifru_flags, flags);
|
|
|
|
if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0)
|
|
return IP_FALSE;
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_resolve_lla
|
|
*===========================================================================
|
|
* Description: Resolve the LLA of the interface
|
|
* Parameters: ctx - Context
|
|
* proc - Process
|
|
* iff - Interface
|
|
* Returns: IP_TRUE on success; IP_FALSE otherwise.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip_if_resolve_lla(Ipmip_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_if_t *iff)
|
|
{
|
|
|
|
Ipmip_buffer_t req;
|
|
Ipmip_buffer_t answer;
|
|
struct Ip_ifinfomsg *ifi;
|
|
struct Ip_nlmsghdr *nlh;
|
|
int ret;
|
|
Ip_size_t nlh_size;
|
|
Ip_size_t addr_size = 0;
|
|
Ip_u8 *addr_data = IP_NULL;
|
|
|
|
ipmip_buffer_init(&req);
|
|
ipmip_buffer_init(&answer);
|
|
|
|
/**/
|
|
ipmip_netlink_nlmsghdr_request(&req, 0, 0, IP_RTM_GETLINK, 0);
|
|
|
|
ifi = (struct Ip_ifinfomsg *)ipmip_buffer_offset(&req, ipmip_netlink_nlmsghdr_put(&req, IP_NULL, sizeof(*ifi)));
|
|
ipcom_memset(ifi, 0, sizeof(*ifi));
|
|
|
|
ifi->ifi_family = IP_AF_LINK;
|
|
ifi->ifi_index = iff->ifindex;
|
|
|
|
ipmip_netlink_nlmsghdr_done(&req, 0);
|
|
|
|
ret = ipmip_netlink_request(ctx, proc, ctx->nl_req, 0, 0, IPMIP_BUFFER_PTR(&req), &answer);
|
|
ipmip_buffer_release(&req);
|
|
|
|
if (ret < 0)
|
|
return IP_FALSE;
|
|
|
|
/* We've gotten an answer */
|
|
nlh = IPMIP_BUFFER_PTR(&answer);
|
|
nlh_size = IPMIP_BUFFER_SIZE(&answer);
|
|
|
|
/**/
|
|
while (IP_NLMSG_OK(nlh, nlh_size))
|
|
{
|
|
/**/
|
|
if (nlh->nlmsg_type == IP_RTM_NEWLINK)
|
|
{
|
|
struct Ip_rtattr *iflap[IP_IFLA_MAX + 1];
|
|
Ip_u8 ll_type;
|
|
Ip_u8 ll_subtype;
|
|
|
|
/* Resolve this entry; I want the prefix length and the address */
|
|
ifi = IP_NLMSG_DATA(nlh);
|
|
|
|
/* Parse */
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_IFLA_MAX + 1,
|
|
IP_IFLA_RTA(ifi),
|
|
IP_IFLA_PAYLOAD(nlh),
|
|
iflap);
|
|
|
|
if (ipmip_lladdr_arphdr_to_lltype(ifi->ifi_type, &ll_type, &ll_subtype))
|
|
{
|
|
/* Need to subresolve any ethernet? */
|
|
if (ll_type == IPMIP_LLADDR_TYPE_MAC && ll_subtype == IPMIP_LLADDR_SUBTYPE_MAC_802_3)
|
|
{
|
|
struct Ip_rtattr *linfo = iflap[IP_IFLA_LINKINFO];
|
|
if (linfo)
|
|
{
|
|
linfo = ipmip_netlink_nlmsghdr_rta_find(IP_RTA_DATA(linfo), IP_RTA_PAYLOAD(linfo), IP_IFLA_INFO_KIND);
|
|
if (linfo != IP_NULL)
|
|
{
|
|
if (ipcom_strcmp("vlan", IP_RTA_DATA(linfo)) == 0)
|
|
ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_1Q;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Found one */
|
|
if (iflap[IP_IFLA_ADDRESS])
|
|
{
|
|
/* Found a LLA address */
|
|
addr_size = IP_RTA_PAYLOAD(iflap[IP_IFLA_ADDRESS]);
|
|
addr_data = IP_RTA_DATA(iflap[IP_IFLA_ADDRESS]);
|
|
}
|
|
|
|
/* Time to create */
|
|
|
|
/* Free old */
|
|
if (iff->lladdr != IP_NULL)
|
|
ipcom_free(iff->lladdr);
|
|
|
|
/* Initialize the structure; used in router advertisements */
|
|
iff->lladdr = ipmip_lladdr_build(IP_NULL,
|
|
ll_type,
|
|
ll_subtype,
|
|
addr_data,
|
|
addr_size);
|
|
|
|
ipmip_buffer_release(&answer);
|
|
return IP_TRUE;
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG1(ERR, "UNSUCCESSFUL ARPHRD FOR %s", iff->ifname);
|
|
}
|
|
}
|
|
|
|
/**/
|
|
nlh = IP_NLMSG_NEXT(nlh, nlh_size);
|
|
}
|
|
|
|
IPCOM_LOG1(ERR, "FAILED TO RESOLVE MAC FOR %s", iff->ifname);
|
|
ipmip_buffer_release(&answer);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_findbyindex
|
|
*===========================================================================
|
|
* Description: Locate an interface in our configuration based on index
|
|
* Parameters: iflist - The list of interfaces
|
|
* idx - The interface index
|
|
* Returns: The interface pointer if it exists, IP_NULL otherwise.
|
|
*/
|
|
IP_GLOBAL Ipmip_if_t *
|
|
ipmip_if_findbyindex(Ipcom_list *iflist,
|
|
Ip_u32 idx)
|
|
{
|
|
Ipmip_if_t *iff;
|
|
|
|
for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next))
|
|
{
|
|
if (iff->ifindex == 0)
|
|
continue;
|
|
|
|
if (iff->ifindex == idx)
|
|
return iff;
|
|
}
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip_if_findbyname
|
|
*===========================================================================
|
|
* Description: Locate an interface in our configuration based on name.
|
|
* Parameters: iflist - The list of interfaces.
|
|
* ifname - The interface name
|
|
* Returns: The interface pointer if it exists, IP_NULL otherwise.
|
|
*/
|
|
IP_GLOBAL Ipmip_if_t *
|
|
ipmip_if_findbyname(Ipcom_list *iflist,
|
|
const char *ifname)
|
|
{
|
|
Ipmip_if_t *iff;
|
|
|
|
ip_assert(ifname);
|
|
|
|
for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next))
|
|
{
|
|
if (*ifname == '\0' || ipcom_strcmp(iff->ifname, ifname) == 0)
|
|
return iff;
|
|
}
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|