984 lines
36 KiB
C
984 lines
36 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipfa_if.c,v $ $Revision: 1.29.10.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmipfa/src/ipmipfa_if.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
#include "ipmipfa_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_cmd.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>
|
|
|
|
#if 0
|
|
#include <ipnet_routesock.h>
|
|
#include <ipnet_policy_routing.h>
|
|
#endif
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_sysvar.h>
|
|
#include <private/ipmip_netlink.h>
|
|
|
|
#include <ipmip4.h>
|
|
#include <private/ipmip4_sysext.h>
|
|
#include <private/ipmip4_util.h>
|
|
#include <private/ipmip4_auth.h>
|
|
#include <private/ipmip4_pkt.h>
|
|
|
|
#include "ipmipfa.h"
|
|
#include "ipmipfa_h.h"
|
|
#include "ipmipfa_if.h"
|
|
#include "ipmipfa_agent.h"
|
|
#include "ipmipfa_reg.h"
|
|
#include "ipmipfa_node.h"
|
|
#include "ipmipfa_route.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipmipfa_iff_tunnel
|
|
{
|
|
Ipmip4_if_t iff;
|
|
Ipmipfa_iff_t *master;
|
|
#if 0
|
|
struct Ipnet_policy_routing_rule blk_rt_rule; /* Tunneled IF to Tunnel rule table */
|
|
struct Ipnet_policy_routing_rule lkl_rt_rule; /* Local IF to Tunnel rule table */
|
|
#endif
|
|
}
|
|
Ipmipfa_iff_tunnel_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_delete
|
|
*===========================================================================
|
|
* Description: Delete an interface
|
|
* Parameters: iff - The interface to delete.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipfa_if_delete(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff)
|
|
{
|
|
/* Free the final resources */
|
|
int i;
|
|
|
|
ipmipfa_llh_config_exit(data, proc, iff);
|
|
|
|
|
|
/* free spi list */
|
|
ipmip4_auth_context_destroy(iff->security.spi_ctx);
|
|
|
|
/* Free the SPI route tables */
|
|
ipmip4_auth_spi_table_destroy(iff->security.spi_ha);
|
|
ipmip4_auth_spi_table_destroy(iff->security.spi_fa);
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELRULE,
|
|
iff->tnl_table,
|
|
IPMIPFA_ROUTE_PRID(0),
|
|
iff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
|
|
/* Destroy the tunnels */
|
|
for (i = 0; i < IPMIP_TUNNELTYPE_MAX; i++)
|
|
{
|
|
if (iff->tunnels[i] != IP_NULL)
|
|
ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->tunnels[i]->ipmip);
|
|
}
|
|
|
|
/* Destroy the node context */
|
|
ipmipfa_node_context_destroy(data, proc, iff->node);
|
|
|
|
/* Destroy black hole route table */
|
|
ipmip_util_route_table_free(&data->ipmip4.ipmip, proc, iff->fwd_table);
|
|
ipmip_util_route_table_free(&data->ipmip4.ipmip, proc, iff->tnl_table);
|
|
|
|
if (iff->link_layer)
|
|
ipcom_free(iff->link_layer);
|
|
|
|
/* Destroy the lock */
|
|
ipmip_timer_lock_destroy(&data->ipmip4.ipmip, proc, iff->if_lock);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_alloc
|
|
*===========================================================================
|
|
* Description: Allocate a specified interface, and verify arch specific
|
|
* data.
|
|
* Parameters: data - The FA data structure.
|
|
* ifname - The interface name.
|
|
* Returns: The interface structure if successfull; IP_NULL otherwise.
|
|
*
|
|
*/
|
|
IP_STATIC Ipmipfa_iff_t *
|
|
ipmipfa_if_alloc(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
const char *ifname)
|
|
{
|
|
/* Allocate an interface structure */
|
|
Ipmipfa_iff_t *iff = IP_NULL;
|
|
Ip_u32 ifindex;
|
|
|
|
ifindex = ipcom_if_nametoindex(ifname);
|
|
if (ifindex == 0)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unknown interface '%s'", ifname));
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/* Allocate the structure */
|
|
iff = (Ipmipfa_iff_t*)ipmip4_if_alloc(&data->ipmip4,
|
|
proc,
|
|
sizeof(*iff),
|
|
ifname,
|
|
ifindex,
|
|
IPMIP_IF_TYPE_GENERIC,
|
|
IPMIPFA_IFF_IDENTITY_FA,
|
|
(Ipmip_if_cleanup_t )ipmipfa_if_delete);
|
|
|
|
/* Sanity */
|
|
if (iff == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
/* Return the interface structure */
|
|
return iff;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_challenge_next
|
|
*===========================================================================
|
|
* Description: Generate the next challenge.
|
|
* Parameters: iff - The interface we're working on.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipfa_if_challenge_next(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff)
|
|
{
|
|
int i;
|
|
/* Advance */
|
|
iff->current_challenge++;
|
|
|
|
/* The index */
|
|
i = iff->current_challenge % IPMIPFA_CONF_CHALLENGE_WINDOW;
|
|
|
|
/* Generate it */
|
|
ipmipfa_if_challenge_generate(data, proc, iff, iff->challenge_window[i]);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_output_timeout
|
|
*===========================================================================
|
|
* Description: Periodically send RtAdv.
|
|
* Parameters: iff - The interface we're sending on.
|
|
* Returns: IP_TRUE
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmipfa_if_advert_output_timeout(int event,
|
|
Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff,
|
|
void *extra)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(extra);
|
|
if (event == IPMIP_TIMER_EVENT_RUN)
|
|
{
|
|
if (IP_BIT_ISFALSE(data->shutdown, IPMIPFA_SHUTDOWN_MUTE))
|
|
{
|
|
/* Generate next challenge */
|
|
ipmipfa_if_challenge_next(data, proc, iff);
|
|
|
|
/* Output it */
|
|
ipmipfa_agent_advert_output(data, proc, iff, IP_NULL, IP_NULL, IP_NULL, IP_FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Do nothing on cancellation */
|
|
}
|
|
|
|
return IPMIP_TIMER_RET_REINSERT;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_destroy_tunnel
|
|
*===========================================================================
|
|
* Description: Destroy a particular tunnel.
|
|
* Parameters: tunnel - The tunnel to destroy.
|
|
* Returns:
|
|
*/
|
|
IP_STATIC void
|
|
ipmipfa_if_destroy_tunnel(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_tunnel_t *iff)
|
|
{
|
|
/* No tunnel, don't bother */
|
|
if (iff->iff.ipmip.ifindex == 0)
|
|
return;
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELRULE,
|
|
data->route->blk_table,
|
|
IPMIPFA_ROUTE_PRID(-2),
|
|
iff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELRULE,
|
|
iff->master->fwd_table,
|
|
IPMIPFA_ROUTE_PRID(-1),
|
|
iff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_create_tunnel
|
|
*===========================================================================
|
|
* Description: Create a specific tunnel for the provided interface
|
|
* Parameters: data - The FA configuration data structure
|
|
* iff - The interface in question.
|
|
* iname - Instance name
|
|
* num - Configuration instance num
|
|
* remote - The remote end
|
|
* identity - The identity
|
|
* tunnel_type - Kind of tunnel.
|
|
* Returns: A newly allocated tunnel instance
|
|
*
|
|
*/
|
|
IP_STATIC Ipmip4_if_t *
|
|
ipmipfa_if_create_tunnel(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff,
|
|
Ip_u32 ifindex,
|
|
Ip_u32 remote,
|
|
Ip_u8 identity,
|
|
Ip_u8 tunnel_type)
|
|
{
|
|
Ipmipfa_iff_tunnel_t *tiff;
|
|
char ifname[IP_IFNAMSIZ + 1];
|
|
|
|
/* Create the name */
|
|
ipcom_snprintf(ifname, sizeof(ifname), "%s%dfa%x", ipmip_util_tunnel_to_bsdname(tunnel_type), tunnel_type, ifindex);
|
|
|
|
tiff = (Ipmipfa_iff_tunnel_t*)ipmip4_if_alloc_tunnel(&data->ipmip4,
|
|
proc,
|
|
sizeof(*tiff),
|
|
ifname,
|
|
iff->iff.ifaddr,
|
|
data->ipmip4.pkt->s_udp_out.sin_port,
|
|
remote,
|
|
identity,
|
|
tunnel_type,
|
|
iff->reordering,
|
|
(Ipmip_if_cleanup_t )ipmipfa_if_destroy_tunnel);
|
|
if (tiff == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
|
|
/* Store master interface */
|
|
tiff->master = iff;
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_NEWRULE,
|
|
data->route->blk_table,
|
|
IPMIPFA_ROUTE_PRID(-2),
|
|
tiff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_NEWRULE,
|
|
iff->fwd_table,
|
|
IPMIPFA_ROUTE_PRID(-1),
|
|
tiff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
IPMIP4_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Created tunnel interface '%s'", tiff->iff.ipmip.ifname));
|
|
|
|
return &tiff->iff;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_configure
|
|
*===========================================================================
|
|
* Description: Post creation configuration
|
|
* Parameters: data - The data
|
|
* proc - Current process
|
|
* iff - The interface we're configuring.
|
|
* conf - The configuration context.
|
|
* Returns: IP_TRUE if successful
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmipfa_if_configure(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff,
|
|
Ipmipfa_conf_t *conf)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(conf);
|
|
/* If we don't have the FA address, try resolve it */
|
|
if (iff->iff.ifaddr == 0)
|
|
{
|
|
/* Store extracted address */
|
|
iff->iff.ifaddr = ipmip4_if_get_primary_address(&data->ipmip4, proc, &iff->iff);
|
|
|
|
/* Sanity */
|
|
if (iff->iff.ifaddr == IP_INADDR_NONE ||
|
|
iff->iff.ifaddr == IP_INADDR_ANY)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"auto-configuring: FAIL, %s returned for interface '%s'",
|
|
ipmip_ntop_inet(proc, iff->iff.ifaddr),
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/**/
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"auto-configuring: interface '%s' configured to use CoA %s",
|
|
iff->iff.ipmip.ifname,
|
|
ipmip_ntop_inet(proc, iff->iff.ifaddr)));
|
|
}
|
|
|
|
/* Get MAC address. */
|
|
if (ipmip_if_resolve_lla(&data->ipmip4.ipmip, proc, &iff->iff.ipmip) == IP_FALSE)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unable to retrieve link-layer address for interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* Need to install the routing policy forcing traffic to the fwd table */
|
|
{
|
|
int i;
|
|
|
|
/*!!CALLED ONCE PER INTERFACE?? ADV_FD ONE PER INTERFACE?? Listen to solicitations sent to 224.0.0.1 */
|
|
if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLHOSTS_GROUP), iff->iff.ipmip.ifindex))
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unable to join all hosts group on interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* Listen to solicitations sent to 224.0.0.2 */
|
|
if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLRTRS_GROUP), iff->iff.ipmip.ifindex))
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unable to join all routers group on interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* Listen to solicitations sent to the Mobile-Agents multicast group 224.0.0.11 */
|
|
if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLMA_GROUP), iff->iff.ipmip.ifindex))
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unable to join all mobile agents group on interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
if (iff->adv_address != ip_htonl(IP_INADDR_ALLHOSTS_GROUP) &&
|
|
iff->adv_address != ip_htonl(IP_INADDR_ALLRTRS_GROUP) &&
|
|
iff->adv_address != ip_htonl(IP_INADDR_ALLMA_GROUP) &&
|
|
IP_IN_CLASSD(iff->adv_address))
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Bad advertisement group %s on interface '%s'",
|
|
ipmip_ntop_inet(proc, iff->adv_address),
|
|
iff->iff.ipmip.ifname));
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* IPIP tunnel */
|
|
for (i = 0; i < IPMIP_TUNNELTYPE_MAX; i++)
|
|
{
|
|
if (iff->tunnel.enabled[i])
|
|
iff->tunnels[i] = ipmipfa_if_create_tunnel(data,
|
|
proc,
|
|
iff,
|
|
iff->iff.ipmip.ifindex,
|
|
IP_INADDR_ANY,
|
|
IPMIPFA_IFF_IDENTITY_FA_TUNNEL,
|
|
i);
|
|
}
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_create
|
|
*===========================================================================
|
|
* Description: Create an interface for a specified configuration.
|
|
* Parameters: data - The FA entity.
|
|
* proc - Current process.
|
|
* conf - The current configuration.
|
|
* ifname - The name of the interface.
|
|
* Returns: IP_TRUE if successful.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmipfa_if_create(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_conf_t *conf,
|
|
const char *ifname)
|
|
{
|
|
Ipmipfa_iff_t *iff;
|
|
int i;
|
|
unsigned si;
|
|
char *dptr;
|
|
|
|
|
|
/* Try create the interface in question */
|
|
if ((iff = ipmipfa_if_alloc(data,proc,ifname)) == IP_NULL)
|
|
return IP_FALSE;
|
|
/**/
|
|
if ((iff->node = ipmipfa_node_context_alloc(data, proc)) == IP_NULL)
|
|
goto fail;
|
|
|
|
iff->tnl_table = ipmip_util_route_table_alloc(&data->ipmip4.ipmip, proc);
|
|
iff->fwd_table = ipmip_util_route_table_alloc(&data->ipmip4.ipmip, proc);
|
|
|
|
ipmip_netlink_inX_rule(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_NEWRULE,
|
|
iff->tnl_table,
|
|
IPMIPFA_ROUTE_PRID(0),
|
|
iff->iff.ipmip.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
|
|
|
|
iff->conf = conf;
|
|
|
|
/* Initialize the lock */
|
|
iff->if_lock = ipmip_timer_lock_alloc(&data->ipmip4.ipmip, proc, IP_NULL, IP_NULL);
|
|
|
|
/* Create the security setup */
|
|
iff->security.spi_ctx = ipmip4_auth_context_create();
|
|
iff->security.spi_ha = ipmip4_auth_spi_table_create(iff->security.spi_ctx);
|
|
iff->security.spi_fa = ipmip4_auth_spi_table_create(iff->security.spi_ctx);
|
|
|
|
/* Initialize ADV timeout */
|
|
IPMIP_TIMER_INIT(&iff->adv_timer);
|
|
|
|
/**/
|
|
ipcom_list_init(&iff->fa_head);
|
|
|
|
/* Store it */
|
|
ipcom_list_insert_first(&conf->if_head, &iff->iff.ipmip.next);
|
|
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi,
|
|
iff->security.spi_ctx,
|
|
"ipmipfa.if.%s.spi.*",
|
|
iff->iff.ipmip.ifname);
|
|
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi,
|
|
iff->security.spi_ctx,
|
|
"ipmipfa.spi.*");
|
|
|
|
/* Read the SPI lookup definitions */
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute,
|
|
iff->security.spi_ha,
|
|
"ipmipfa.if.%s.ha.sa.address.*",
|
|
iff->iff.ipmip.ifname);
|
|
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute,
|
|
iff->security.spi_ha,
|
|
"ipmipfa.ha.sa.address.*");
|
|
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute,
|
|
iff->security.spi_fa,
|
|
"ipmipfa.if.%s.fa.sa.address.*", iff->iff.ipmip.ifname);
|
|
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute,
|
|
iff->security.spi_fa,
|
|
"ipmipfa.fa.sa.address.*");
|
|
|
|
iff->security.spi_ha_lookup_required = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.ha.sa.lookup.required"), "ipmipfa.if.%s.ha.sa.lookup.required", iff->iff.ipmip.ifname);
|
|
|
|
/* Get foreign agent addresses. Reachable by foreign subnets. */
|
|
ipmip_sysvar_inet(0, &iff->iff.ifaddr, IP_NULL, "ipmipfa.if.%s.foreignagent", iff->iff.ipmip.ifname);
|
|
|
|
/* Get ADV lifetime */
|
|
iff->mn_auth = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.mn_auth"), "ipmipfa.if.%s.mn_auth", iff->iff.ipmip.ifname);
|
|
|
|
/* Get ADV lifetime */
|
|
iff->adv_lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(300, "ipmipfa.adv_lifetime"), "ipmipfa.if.%s.adv_lifetime", iff->iff.ipmip.ifname);
|
|
|
|
/* Get ADV interval */
|
|
iff->adv_interval = ipmip_sysvar_long(10, "ipmipfa.if.%s.adv_interval", iff->iff.ipmip.ifname);
|
|
|
|
iff->lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(ipmip_sysvar_ulong(60, "ipmipfa.lifetime"), "ipmipfa.reg_lifetime"), "ipmipfa.if.%s.lifetime", iff->iff.ipmip.ifname);
|
|
if (iff->lifetime == 0)
|
|
iff->lifetime = 0xffff; /* infinite */
|
|
|
|
/* Get ADV address */
|
|
if (!ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipfa.if.%s.adv_address", iff->iff.ipmip.ifname))
|
|
ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipfa.adv_address");
|
|
|
|
if (iff->adv_address == 0)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Bad advertisement group %s on interface '%s'",
|
|
ipmip_ntop_inet(proc, iff->adv_address),
|
|
iff->iff.ipmip.ifname));
|
|
goto fail;
|
|
}
|
|
|
|
/* FA Error Extension (RFC4636) */
|
|
iff->ext.fa_error = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.ext.fa_error"), "ipmipfa.if.%s.ext.fa_error", iff->iff.ipmip.ifname);;
|
|
|
|
/* DHAA (RFC4433) */
|
|
iff->ext.dhaa = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.ext.dhaa"), "ipmipfa.if.%s.ext.dhaa", iff->iff.ipmip.ifname);
|
|
|
|
|
|
if (!ipmip_sysvar_inet(0, &iff->ext.dhaa_address, IP_NULL, "ipmipfa.if.%s.ext.dhaa.address", iff->iff.ipmip.ifname))
|
|
ipmip_sysvar_inet(0, &iff->ext.dhaa_address, IP_NULL, "ipmipfa.ext.dhaa.address");
|
|
|
|
/* Challenge (RFC3012) */
|
|
iff->ext.challenge = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.challenge"), "ipmipfa.if.%s.challenge", iff->iff.ipmip.ifname);
|
|
|
|
/* */
|
|
iff->ext.revocation = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.revocation.enabled"), "ipmipfa.if.%s.revocation.enabled", iff->iff.ipmip.ifname);
|
|
iff->ext.revocation_inform = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipfa.revocation.inform"), "ipmipfa.if.%s.revocation.inform", iff->iff.ipmip.ifname);
|
|
|
|
/* Reverse tunneling state? */
|
|
iff->tunnel.reverse = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipfa.tunnel.reverse"), "ipmipfa.if.%s.tunnel.reverse", iff->iff.ipmip.ifname);
|
|
|
|
/**/
|
|
iff->tunnel.enabled[IPMIP_TUNNELTYPE_NONE] = IP_TRUE;
|
|
|
|
/* Get tunnel reordering */
|
|
iff->reordering = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.tunnel.reordering"), "ipmipfa.if.%s.tunnel.reordering", iff->iff.ipmip.ifname);
|
|
|
|
/**/
|
|
iff->tunnel.enabled[IPMIP_TUNNELTYPE_IPIP] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.ipip"), "ipmipfa.if.%s.tunnel.ipip", iff->iff.ipmip.ifname);
|
|
|
|
/* GRE allowed? */
|
|
iff->tunnel.enabled[IPMIP_TUNNELTYPE_GRE] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.gre"), "ipmipfa.if.%s.tunnel.gre", iff->iff.ipmip.ifname);
|
|
|
|
/* MINENC allowed? */
|
|
iff->tunnel.enabled[IPMIP_TUNNELTYPE_MINENC] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.minenc"), "ipmipfa.if.%s.tunnel.minenc", iff->iff.ipmip.ifname);
|
|
|
|
/* NAT-T enabled? */
|
|
iff->nat_t = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.nat_t.enabled"), "ipmipfa.if.%s.nat_t.enabled", iff->iff.ipmip.ifname);
|
|
|
|
/* NAT-T keepalive? */
|
|
iff->nat_t_keepalive = (Ip_u8)ipmip_sysvar_ulong(ipmip_sysvar_ulong(120, "ipmipfa.nat_t.keepalive"), "ipmipfa.if.%s.nat_t.keepalive", iff->iff.ipmip.ifname);
|
|
|
|
/* NAT-T forced if enabled? */
|
|
iff->nat_t_force = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.nat_t.forced"), "ipmipfa.if.%s.nat_t.forced", iff->iff.ipmip.ifname);
|
|
|
|
/* Get tunnel type */
|
|
i = ipmip4_sysext_tunnel_type(ipmip4_sysext_tunnel_type(IPMIP_TUNNELTYPE_NONE, "ipmipfa.nat_t.tunnel_type"), "ipmipfa.if.%s.nat_t.tunnel_type", iff->iff.ipmip.ifname);
|
|
if (i == -1)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"invalid 'nat_t.tunnel_type' configuration in UDP encap for interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
goto fail;
|
|
}
|
|
|
|
iff->nat_t_tunnel = (Ip_u8)i;
|
|
|
|
/* Configure the interface */
|
|
if (ipmipfa_if_configure(data, proc, iff, conf) == IP_FALSE)
|
|
goto fail;
|
|
|
|
/* Generate a window full of challenges */
|
|
for (i = 0; i < IPMIPFA_CONF_CHALLENGE_WINDOW; i++)
|
|
ipmipfa_if_challenge_next(data, proc, iff);
|
|
|
|
if ((dptr = ipmip_sysvar("ipmipfa.if.%s.link.layer", iff->iff.ipmip.ifname)) == IP_NULL)
|
|
dptr = ipmip_sysvar("ipmipfa.link.layer");
|
|
|
|
|
|
/* */
|
|
if (dptr != IP_NULL)
|
|
{
|
|
iff->link_layer = ipmip_lladdr_parse(proc, iff->iff.ipmip.lladdr->type, iff->iff.ipmip.lladdr->subtype, dptr);
|
|
ipcom_free(dptr);
|
|
|
|
if (iff->link_layer)
|
|
{
|
|
ipmip_if_clear_flags(&data->ipmip4.ipmip, proc, &iff->iff.ipmip, IP_IFF_UP);
|
|
|
|
/* Assign LLADDR */
|
|
if (ipmip_netlink_link(&data->ipmip4.ipmip,
|
|
proc,
|
|
IP_RTM_SETLINK,
|
|
iff->iff.ipmip.ifindex,
|
|
0,
|
|
0,
|
|
IPMIP_LLADDR_DATA(iff->link_layer),
|
|
IPMIP_LLADDR_LEN_LLA(iff->link_layer),
|
|
0) != 0)
|
|
{
|
|
/* Do something */
|
|
IPMIP4_EVENT_IF(WARNING, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Foreign Agent interface %s unable to assign Link-Layer address",
|
|
iff->iff.ipmip.ifname));
|
|
}
|
|
|
|
ipmip_if_set_flags(&data->ipmip4.ipmip, proc, &iff->iff.ipmip, IP_IFF_UP);
|
|
|
|
/**/
|
|
if (ipmip_if_resolve_lla(&data->ipmip4.ipmip, proc, &iff->iff.ipmip) == IP_FALSE)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Unable to retrieve assigned link-layer address for interface '%s'",
|
|
iff->iff.ipmip.ifname));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ipmipfa_llh_config_read(data, proc, iff);
|
|
|
|
/* Do the external parsing */
|
|
for (i = IPMIPFA_FUNCTION_MAX - 1; i >= 0; i--)
|
|
{
|
|
for (si = 0; si < data->extensions[i].num; si++)
|
|
{
|
|
if (data->extensions[i].functions[si]->config_ifp != IP_NULL)
|
|
{
|
|
if (data->extensions[i].functions[si]->ifp_data_size)
|
|
{
|
|
iff->extdata[i][si] = ipcom_calloc(1, data->extensions[i].functions[si]->ifp_data_size);
|
|
(*data->extensions[i].functions[si]->config_ifp) (data, proc, IPMIP_CALLBACK_CONFIG_READ, iff, conf->extdata[i][si], iff->extdata[i][si], IP_NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return IP_TRUE;
|
|
|
|
fail:
|
|
ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->iff.ipmip);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
IP_GLOBAL void *
|
|
ipmipfa_if_extension_data(Ipmipfa_iff_t *ifp,
|
|
Ipmipfa_extension_t *ext)
|
|
{
|
|
if (ext->ifp_data_size == 0)
|
|
return IP_NULL;
|
|
|
|
return ifp->extdata[ext->func][ext->type];
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_start
|
|
*===========================================================================
|
|
* Description: Start an interface for a specified configuration.
|
|
* Parameters: data - The FA entity.
|
|
* proc - Current process.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmipfa_if_stop(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_conf_t *conf)
|
|
{
|
|
Ipmipfa_iff_t *iff;
|
|
|
|
/* Send instant RtAdv on all active interfaces */
|
|
while (IP_NULL != (iff = IPCOM_LIST_FIRST(&conf->if_head)))
|
|
{
|
|
int i;
|
|
unsigned si;
|
|
|
|
for (i = IPMIPFA_FUNCTION_MAX - 1; i >= 0; i--)
|
|
{
|
|
for (si = 0; si < data->extensions[i].num; si++)
|
|
{
|
|
if (data->extensions[i].functions[si]->config_ifp != IP_NULL)
|
|
{
|
|
if (iff->extdata[i][si])
|
|
{
|
|
(*data->extensions[i].functions[si]->config_ifp) (data, proc, IPMIP_CALLBACK_CONFIG_FREE, iff, conf->extdata[i][si], iff->extdata[i][si], IP_NULL);
|
|
ipcom_free(iff->extdata[i][si]);
|
|
iff->extdata[i][si] = IP_NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->iff.ipmip);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_start
|
|
*===========================================================================
|
|
* Description: Start an interface for a specified configuration.
|
|
* Parameters: data - The FA entity.
|
|
* proc - Current process.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmipfa_if_start(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
Ipmipfa_iff_t *iff;
|
|
|
|
if (data->conf == IP_NULL)
|
|
return;
|
|
|
|
/* Send instant RtAdv on all active interfaces */
|
|
for (iff = IPCOM_LIST_FIRST(&data->conf->if_head); iff; iff = IPCOM_LIST_NEXT(&iff->iff.ipmip.next))
|
|
{
|
|
/* Is it activated? */
|
|
if (iff->adv_interval > 0)
|
|
{
|
|
ipmip_timer_request(&data->ipmip4.ipmip,
|
|
proc,
|
|
&iff->adv_timer,
|
|
iff->if_lock,
|
|
(Ipmip_timer_func_t)ipmipfa_if_advert_output_timeout,
|
|
iff,
|
|
IP_NULL,
|
|
iff->adv_interval * 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipfa_if_challenge_generate
|
|
*===========================================================================
|
|
* Description: Generate a challenge
|
|
* Parameters: data - Context
|
|
* proc - Process
|
|
* iff - The interface the challenge belongs to.
|
|
* challenge - Where to store the challenge.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmipfa_if_challenge_generate(Ipmipfa_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipfa_iff_t *iff,
|
|
Ip_u8 *challenge)
|
|
{
|
|
struct Ip_timeval tv;
|
|
int i;
|
|
|
|
IPMIP_UNUSED_PARAMETER(iff);
|
|
IPMIP_UNUSED_PARAMETER(data);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
ipcom_microtime(&tv);
|
|
ipcom_srandom((unsigned int) (tv.tv_sec + tv.tv_usec));
|
|
|
|
for (i = 0; i < IPMIPFA_CONF_CHALLENGE_LEN; i++)
|
|
challenge[i] = (Ip_u8) ipcom_random();
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|