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

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
****************************************************************************
*/