724 lines
22 KiB
C
724 lines
22 KiB
C
/*
|
|
*******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipha_main.c,v $ $Revision: 1.9.16.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmipha/src/ipmipha_main.c,v $
|
|
* $Author: jsheng $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Niklas Lundberg <n@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* 1 DESCRIPTION
|
|
*******************************************************************************
|
|
*
|
|
* Legend:
|
|
* HA = Home agent
|
|
* MN = Mobile node
|
|
* FA = Foreign agent
|
|
* CN = Correspondent node (someone on the internet the mobile node talks to
|
|
* via the HA)
|
|
* COA = Care-of address
|
|
*
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipmipha_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_sysctl.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_syslog.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_timer.h>
|
|
#include <private/ipmip_sysvar.h>
|
|
#include <private/ipmip_cli.h>
|
|
|
|
#include <ipmip4.h>
|
|
#include <private/ipmip4_context.h>
|
|
#include <private/ipmip4_util.h>
|
|
#include <private/ipmip4_sysext.h>
|
|
#include <private/ipmip4_auth.h>
|
|
#include <private/ipmip4_pkt.h>
|
|
#include <private/ipmip4_pktbuf.h>
|
|
#include <private/ipmip4_diameter.h>
|
|
|
|
#include "ipmipha.h"
|
|
#include "ipmipha_h.h"
|
|
#include "ipmipha_attr_h.h"
|
|
#include "ipmipha_if.h"
|
|
#include "ipmipha_node.h"
|
|
#include "ipmipha_reg.h"
|
|
#include "ipmipha_agent.h"
|
|
#include "ipmipha_route.h"
|
|
#include "ipmipha_pktbuf.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Private Application datatypes
|
|
*===========================================================================
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Registration request and reply
|
|
*===========================================================================
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipmipha_rtmsg
|
|
*===========================================================================
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_PUBLIC Ip_err ipmipha_create(void);
|
|
IP_PUBLIC Ip_err ipmipha_start(void);
|
|
IP_PUBLIC Ip_err ipmipha_init(void);
|
|
IP_PUBLIC Ip_err ipmipha_exit(void);
|
|
IP_PUBLIC Ip_err ipmipha_configure(void);
|
|
|
|
IP_PUBLIC const char *ipmipha_version(void);
|
|
|
|
#ifdef IPSNMP
|
|
IP_EXTERN Ip_err ipmipha_mip_mib_init(void);
|
|
IP_EXTERN Ip_err ipmip4_mip_mib_init(void);
|
|
#endif
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_PUBLIC IPCOM_PROCESS(ipmipha_proc);
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Global IPMIPHA data
|
|
*===========================================================================
|
|
* All global IPMIPHA data is located in this structure.
|
|
*/
|
|
static int ipmipha_instances = 0;
|
|
|
|
static Ipcom_once_t ipmipha_extensions_once = IPCOM_ONCE_INIT;
|
|
static Ipmipha_function_context_t ipmipha_extensions[IPMIPHA_FUNCTION_MAX];
|
|
static Ip_u32 ipmipha_extensions_node_data = 0;
|
|
static Ipcom_list ipmipha_msgext_vendor_extensions;
|
|
static Ipmip_pktbuf_pktaux_t ipmipha_pktaux;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC Ip_err
|
|
ipmipha_main_once_init(void *unused)
|
|
{
|
|
int f;
|
|
|
|
IPMIP_UNUSED_PARAMETER(unused);
|
|
|
|
/* Clear */
|
|
ipcom_memset(&ipmipha_extensions[0], 0, sizeof(ipmipha_extensions));
|
|
ipcom_memset(&ipmipha_pktaux, 0, sizeof(ipmipha_pktaux));
|
|
ipcom_list_init(&ipmipha_msgext_vendor_extensions);
|
|
|
|
/* Do service init */
|
|
for (f = 0; ipmipha_function_registrations[f] != IP_NULL; f++)
|
|
(*ipmipha_function_registrations[f]) ();
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_config_free
|
|
*===========================================================================
|
|
* Description: Clear out a configuration structure, free any resources
|
|
* associated with it.
|
|
* Parameters: data - The HA entity it belongs to
|
|
* proc - The process
|
|
* conf - The configuration structure.
|
|
* Returns:
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_config_free(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc,
|
|
Ipmipha_conf_t *conf)
|
|
{
|
|
ipmipha_if_stop(data, proc, conf);
|
|
|
|
/**/
|
|
ipcom_free(conf);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_config_exit
|
|
*===========================================================================
|
|
* Description: Clears the indicated configuration
|
|
* Parameters: instance - The Home Agent instance we're currently working on.
|
|
* conf - The configuration
|
|
* Returns:
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_config_exit(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
Ipmipha_iff_t *iff;
|
|
|
|
if (data->conf == IP_NULL)
|
|
return;
|
|
|
|
/* Disallow any new regs */
|
|
ipmip4_pkt_context_stop(&data->ipmip4, proc);
|
|
data->shutdown = IPMIPHA_SHUTDOWN_ALL;
|
|
ipmip4_pkt_context_start(&data->ipmip4, proc);
|
|
|
|
/* Free all mobile nodes */
|
|
ipmipha_node_clear(data, proc);
|
|
|
|
/* Stop the current context */
|
|
ipmip4_context_stop(&data->ipmip4, proc);
|
|
|
|
/* free interface list */
|
|
for (iff = IPCOM_LIST_FIRST(&data->conf->if_head); iff != IP_NULL; iff = IPCOM_LIST_NEXT(&iff->iff.ipmip.next))
|
|
{
|
|
if (iff->adv_interval > 0 &&
|
|
iff->iff.ifaddr != 0)
|
|
{
|
|
/* Reduce lifetime to 0 */
|
|
iff->adv_lifetime = 0;
|
|
iff->lifetime = 0;
|
|
ipmipha_agent_advert_output(data, proc, iff, IP_NULL, IP_NULL);
|
|
}
|
|
}
|
|
|
|
/* Free the configuration */
|
|
ipmipha_config_free(data, proc, data->conf);
|
|
data->conf = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_config_read
|
|
*===========================================================================
|
|
* Description: Read IPMIPHA config.
|
|
* used in ipmipha_config_init
|
|
* Parameters: .
|
|
* Returns: .
|
|
*
|
|
*/
|
|
IP_STATIC Ipmipha_conf_t *
|
|
ipmipha_config_read(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
Ipmipha_conf_t *conf;
|
|
char **arr = IP_NULL;
|
|
|
|
conf = ipcom_calloc(1, sizeof(Ipmipha_conf_t));
|
|
if (conf == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
ipcom_list_init(&conf->if_head);
|
|
|
|
/* Find all interfaces */
|
|
arr = ipmip_sysvar_strarr("ipmipha.interfaces");
|
|
if (arr == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Bad configuration. Invalid/missing \"ipmipha.interfaces\""));
|
|
goto fail;
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
for (i = 0; arr[i] != IP_NULL; i++)
|
|
{
|
|
/* If I can't create the interface, exit */
|
|
if (ipmipha_if_create(data, proc, conf, arr[i]) == IP_FALSE)
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
/* Free the interface name buffer */
|
|
ipcom_free(arr);
|
|
return conf; /* success */
|
|
|
|
fail:
|
|
if (arr)
|
|
ipcom_free(arr);
|
|
ipmipha_config_free(data, proc, conf);
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_config_init
|
|
*===========================================================================
|
|
* Description: Initialize the configuration for the specified instance
|
|
* Parameters: instance - The HA instance
|
|
* Returns: 0 on success
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipmipha_config_init(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
Ipmipha_conf_t *conf;
|
|
#ifndef IP_PORT_LAS
|
|
int name[4];
|
|
Ip_size_t oldlenp;
|
|
#endif
|
|
|
|
/* No new nodes*/
|
|
IP_BIT_SET(data->shutdown, IPMIPHA_SHUTDOWN_NODE);
|
|
|
|
if (data->conf)
|
|
ipmipha_config_exit(data, proc);
|
|
|
|
/* Read configuration */
|
|
conf = ipmipha_config_read(data, proc);
|
|
if (conf == IP_NULL)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Configuration Failed - Invalid Configuration"));
|
|
IP_BIT_CLR(data->shutdown, IPMIPHA_SHUTDOWN_NODE);
|
|
ipmip_context_start(&data->ipmip4.ipmip, proc);
|
|
return -1;
|
|
}
|
|
|
|
#ifndef IP_PORT_LAS
|
|
/* Check if we are a router */
|
|
name[0] = IP_CTL_NET;
|
|
name[1] = IP_AF_INET;
|
|
name[2] = IP_IPPROTO_IP;
|
|
name[3] = IP_IPCTL_FORWARDING;
|
|
oldlenp = sizeof(data->ipnet_is_router);
|
|
if (ipcom_sysctl(name, 4, &data->ipnet_is_router, &oldlenp, IP_NULL, IP_NULL) < 0)
|
|
data->ipnet_is_router = 0;
|
|
#endif
|
|
|
|
/* Reconfigure (existing config was in place) */
|
|
data->conf = conf;
|
|
|
|
data->shutdown = 0;
|
|
|
|
ipmip4_context_start(&data->ipmip4, proc);
|
|
ipmipha_if_start(data, proc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_exit_agent
|
|
*===========================================================================
|
|
* Description: Free the HA instance
|
|
* Parameters: instance - The HA instance to free.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmipha_exit_agent(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
/* Sanity */
|
|
if (data == IP_NULL)
|
|
return;
|
|
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"IPMIPHA ending"));
|
|
|
|
/* Stop the context */
|
|
ipmip4_context_stop(&data->ipmip4, proc);
|
|
|
|
/* Destroy route context */
|
|
ipmipha_route_context_destroy(data, proc);
|
|
|
|
/* Exit the IPD */
|
|
if (data->fd_ipd == IP_INVALID_SOCKET)
|
|
(void)ipcom_ipd_init("ipmipha", IPCOM_ERR_FAILED, &data->fd_ipd);
|
|
|
|
(void)ipcom_ipd_exit("ipmipha", data->fd_ipd);
|
|
|
|
/* */
|
|
ipcom_mutex_delete(&data->mibLock);
|
|
|
|
ipmip_context_id_destroy(data->idents);
|
|
|
|
/* Free the context */
|
|
ipmip4_context_destroy(&data->ipmip4, proc);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_init_agent
|
|
*===========================================================================
|
|
* Description: Initialize an agent instance
|
|
* Parameters:
|
|
* Returns: The pointer to the agent instance if successful
|
|
*
|
|
*/
|
|
IP_STATIC Ipmipha_data_t *
|
|
ipmipha_init_agent(Ipmip_proc_t *proc)
|
|
{
|
|
Ipmipha_data_t *data;
|
|
|
|
(void)IPMIP_ONCE(&ipmipha_extensions_once, ipmipha_main_once_init, IP_NULL);
|
|
|
|
|
|
data = (Ipmipha_data_t *)ipmip_context_alloc(proc, sizeof(*data), "ipmipha", IPMIP4_SYSTEM_PRIORITY, IPMIPHA_EVENT_BACKLOG);
|
|
if (data == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
/* Setup the extension structure */
|
|
data->extensions = &ipmipha_extensions[0];
|
|
data->extensions_node_data = &ipmipha_extensions_node_data;
|
|
data->ipmip4.vendor_extensions = &ipmipha_msgext_vendor_extensions;
|
|
data->ipmip4.ipmip.pktaux = &ipmipha_pktaux;
|
|
|
|
ipmip4_context_init(&data->ipmip4, proc);
|
|
|
|
data->fd_ipd = IP_INVALID_SOCKET;
|
|
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"IPMIPHA starting [VR %d]", data->ipmip4.ipmip.vr));
|
|
|
|
(void)ipcom_mutex_create(&data->mibLock);
|
|
|
|
/* IPD init. */
|
|
if (ipcom_ipd_init("ipmipha", IPCOM_SUCCESS, &data->fd_ipd) != IPCOM_SUCCESS)
|
|
goto fail;
|
|
|
|
data->idents = ipmip_context_id_create(ip_offsetof(Ipmipha_node_t, haNodeIdentity), 0xFFFFFFFF);
|
|
|
|
ipmip_cli_context_create(&data->ipmip4.ipmip,
|
|
proc,
|
|
"ipmipha",
|
|
IPCOM_IPD_ID_IPMIPHA,
|
|
(Ipmip_cli_callback_t)ipmipha_attr_command);
|
|
|
|
/* Create the packet buffer context */
|
|
ipmip_pktbuf_context_create(&data->ipmip4.ipmip,
|
|
proc,
|
|
(Ipmip_pkt_buf_alloc_t)ipmipha_pktbuf_alloc,
|
|
(Ipmip_pkt_buf_free_t)ipmipha_pktbuf_free);
|
|
|
|
if (!ipmip4_pkt_context_create(&data->ipmip4,
|
|
proc,
|
|
IPMIP4_PKT_UDP_IN_434|IPMIP4_PKT_PKT_OUT|IPMIP4_PKT_ICMP_IN,
|
|
(Ipmip4_pkt_udp_cb_t)ipmipha_reg_recv,
|
|
(Ipmip4_pkt_icmp_cb_t)ipmipha_adv_recv,
|
|
IP_NULL))
|
|
goto fail;
|
|
|
|
ipmipha_route_context_alloc(data, proc);
|
|
|
|
return data;
|
|
|
|
fail:
|
|
ipmipha_exit_agent(data, proc);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipha_data_process
|
|
*===========================================================================
|
|
* Description: Process any file descriptors set by the platform.
|
|
* Parameters: data - The data structure
|
|
* rset - The read set.
|
|
* Returns: IP_FALSE if we should exit the process.
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipmipha_ipd_process(Ipmipha_data_t *data,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
/* IPD input. */
|
|
int event;
|
|
Ip_ssize_t len;
|
|
Ipmipha_pktbuf_t *pbuf = (Ipmipha_pktbuf_t *)ipmip_pktbuf_alloc(&data->ipmip4.ipmip, proc, 512);
|
|
|
|
if (pbuf == IP_NULL)
|
|
return IP_TRUE;
|
|
|
|
len = ipcom_ipd_read(data->fd_ipd, IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet), 512, &event);
|
|
if (len < 0)
|
|
ipmip_util_sock_clear(data->fd_ipd);
|
|
else
|
|
{
|
|
/* Advance past */
|
|
ipmip_buffer_append(&pbuf->ipmip4.ipmip.packet, IP_NULL, len);
|
|
|
|
switch (event)
|
|
{
|
|
case IPCOM_IPD_EVENT_RECONFIGURE:
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Received IPD reconfigure message"));
|
|
if (ipmipha_config_init(data, proc) != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Invalid new configuration - reconfigure failed and process suspended. Please correct configuration"));
|
|
}
|
|
break;
|
|
|
|
case IPCOM_IPD_EVENT_KILL:
|
|
IPMIP4_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Received IPD kill message"));
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
return IP_FALSE;
|
|
|
|
default:
|
|
/* Ignore all other IPD messages */
|
|
break;
|
|
}
|
|
}
|
|
|
|
ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/* To remove the warning */
|
|
IP_PUBLIC IPCOM_PROCESS(ipmipha_proc);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmiphad
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmipha_main(void)
|
|
{
|
|
char icmp_redirect[8];
|
|
Ip_size_t size = sizeof(icmp_redirect);
|
|
Ipmipha_data_t *data = IP_NULL;
|
|
Ipmip_proc_t *proc;
|
|
|
|
ipcom_proc_init();
|
|
|
|
/* Get me a process context for this thread */
|
|
proc = ipmip_proc_alloc();
|
|
if(IP_NULL == proc)
|
|
goto end;
|
|
|
|
/**/
|
|
ipmipha_configure();
|
|
|
|
/* First instance? */
|
|
if (ipmipha_instances++ == 0)
|
|
ipmipha_init();
|
|
|
|
ipcom_sysvar_get("ipnet.inet.IcmpRedirectSend",
|
|
icmp_redirect,
|
|
&size);
|
|
if (ipcom_sysvar_set("ipnet.inet.IcmpRedirectSend", "0", IPCOM_SYSVAR_FLAG_OVERWRITE) != IPCOM_SUCCESS)
|
|
goto end;
|
|
|
|
/* Init IPMIPHA */
|
|
if ((data = ipmipha_init_agent(proc)) == IP_NULL)
|
|
goto end;
|
|
|
|
/* Init HA from configuration */
|
|
if (ipmipha_config_init(data, proc) != 0)
|
|
{
|
|
IPMIP4_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&data->ipmip4.ipmip,
|
|
proc,
|
|
"Invalid configuration - configure failed and process suspended. Please correct configuration"));
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
int num;
|
|
int max_fd;
|
|
Ip_fd_set read_set;
|
|
|
|
IP_FD_ZERO(&read_set);
|
|
|
|
/* Set the IPD */
|
|
max_fd = data->fd_ipd;
|
|
IP_FD_SET(data->fd_ipd, &read_set);
|
|
|
|
/* Select */
|
|
num = ipcom_socketselect(max_fd + 1, &read_set, IP_NULL, IP_NULL, IP_NULL);
|
|
|
|
switch(num)
|
|
{
|
|
case -1: /* socket error. */
|
|
(void)ipcom_sleep(1);
|
|
break;
|
|
|
|
case 0: /* timeout, not used. triggered by bug in linux glibc if compiled with nptl */
|
|
(void)ipcom_millisleep(1);
|
|
break;
|
|
|
|
default:
|
|
/* Process IPD */
|
|
if (IP_FD_ISSET(data->fd_ipd, &read_set))
|
|
{
|
|
if (ipmipha_ipd_process(data, proc) == IP_FALSE)
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
|
|
end:
|
|
/* If we've gotten the data, clear it */
|
|
if (data != IP_NULL)
|
|
{
|
|
ipmipha_config_exit(data, proc);
|
|
ipmipha_exit_agent(data, proc);
|
|
}
|
|
|
|
(void)ipcom_sysvar_set("ipnet.inet.IcmpRedirectSend",
|
|
icmp_redirect,
|
|
IPCOM_SYSVAR_FLAG_OVERWRITE);
|
|
|
|
|
|
/* Last instance? */
|
|
if (--ipmipha_instances == 0)
|
|
ipmipha_exit();
|
|
|
|
/* Free the context process */
|
|
ipmip_proc_destroy(proc);
|
|
|
|
ipcom_proc_exit();
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* INIT FUNCTIONS */
|
|
IP_GLOBAL Ip_u32
|
|
ipmipha_context_register_extension(Ipmipha_extension_t *srv,
|
|
int function)
|
|
{
|
|
Ipmipha_function_context_t *func = &ipmipha_extensions[function];
|
|
Ip_u32 type = func->num++;
|
|
|
|
/* Store values */
|
|
srv->type = type;
|
|
srv->func = function;
|
|
|
|
/* Create the unique identifier */
|
|
srv->unique = type;
|
|
srv->unique |= function << 16;
|
|
|
|
func->mask |= (1 << type);
|
|
ipmipha_extensions_node_data+= srv->node_data_size;
|
|
ipmipha_extensions_node_data+= sizeof(void *);
|
|
|
|
func->functions[type] = srv;
|
|
func->node_data += srv->node_data_size;
|
|
|
|
/* Register payload, if requested */
|
|
if (srv->pktaux.pktbuf_data_size != 0)
|
|
ipmip_pktbuf_pktaux_add(&ipmipha_pktaux, &srv->pktaux);
|
|
|
|
return srv->unique;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmipha_msgext_vendor_parse_ext_register(struct Ipmip4_msgext_vendor_parse_ext *pext)
|
|
{
|
|
/**/
|
|
ipmip4_msgext_vendor_parse_ext_register(&ipmipha_msgext_vendor_extensions, &ipmipha_pktaux, pext);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|