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

525 lines
16 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6pm_main.c,v $ $Revision: 1.7.16.1 $
* $Source: /home/interpeak/CVSRoot/ipmip6pm/src/ipmip6pm_main.c,v $
* $Author: jhorteli $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip6pm_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <ipcom_type.h>
#include <ipcom_cstyle.h>
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock6.h>
#include <ipcom_inet.h>
#include <ipcom_list.h>
#include <ipcom_ipd.h>
#include <ipcom_syslog.h>
#include <ipmip.h>
#include <private/ipmip_util.h>
#include <private/ipmip_dhcp.h>
#include <private/ipmip_dhcp6.h>
#include <private/ipmip_inet.h>
#include <ipmip6.h>
#include <private/ipmip6_context.h>
#include <private/ipmip6_pkt.h>
#include <private/ipmip6_if.h>
#include <private/ipmip6_mh.h>
#include <private/ipmip6_mh_pkt.h>
#include <private/ipmip6_util.h>
#include "ipmip6pm.h"
#include "ipmip6pm_h.h"
#include "ipmip6pm_node.h"
#include "ipmip6pm_attr_h.h"
#include "ipmip6pm_ifevent.h"
#include "ipmip6pm_mh.h"
#include "ipmip6pm_icmp.h"
#include "ipmip6pm_if.h"
#include "ipmip6pm_route.h"
#include "ipmip6pm_pktbuf.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_PUBLIC Ip_err ipmip6pm_exit(void);
IP_PUBLIC Ip_err ipmip6pm_init(void);
IP_PUBLIC Ip_err ipmip6pm_start(void);
IP_PUBLIC const char *ipmip6pm_version(void);
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static int ipmip6pm_instances = 0;
/* Dispatch function callbacks */
static Ipmip6_pkt_context_dispatch_t ipmip6pm_dispatch_table =
{
(Ipmip6_pkt_dispatch_t)ipmip6pm_mh_dispatch,
(Ipmip6_pkt_dispatch_t)IP_NULL
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC void
ipmip6pm_services_clear(Ipmip6pm_context_t *ctx,
Ipmip_proc_t *proc)
{
unsigned si, f;
for (f = 0; f < IPMIP6PM_FUNCTION_MAX; f++)
{
for (si = 0; si < ctx->extensions[f].num; si++)
{
if (ctx->extensions[f].functions[si]->config_global != IP_NULL && ctx->extdata[f][si])
{
(*ctx->extensions[f].functions[si]->config_global) (ctx, proc, IPMIP_CALLBACK_CONFIG_FREE, ctx->extdata[f][si], IP_NULL);
ipcom_free(ctx->extdata[f][si]);
ctx->extdata[f][si] = IP_NULL;
}
}
}
}
IP_STATIC void
ipmip6pm_services_read(Ipmip6pm_context_t *ctx,
Ipmip_proc_t *proc)
{
unsigned si, f;
for (f = 0; f < IPMIP6PM_FUNCTION_MAX; f++)
{
for (si = 0; si < ctx->extensions[f].num; si++)
{
if (ctx->extensions[f].functions[si]->config_global != IP_NULL && ctx->extensions[f].functions[si]->global_data_size)
{
ctx->extdata[f][si] = ipcom_calloc(1, ctx->extensions[f].functions[si]->global_data_size);;
(*ctx->extensions[f].functions[si]->config_global) (ctx, proc, IPMIP_CALLBACK_CONFIG_READ, ctx->extdata[f][si], IP_NULL);
}
}
}
}
/*
*===========================================================================
* ipmippm_config_init
*===========================================================================
* Description: Initialize the configuration for the specified instance
* Parameters: instance - The PM instance
* Returns: 0 on success
*
*/
IP_STATIC int
ipmip6pm_update_config(Ipmip6pm_context_t *ctx,
Ipmip_proc_t *proc)
{
/* Stop the CLI context */
ipmip_cli_context_stop(&ctx->ipmip6.ipmip, proc);
/* Stop the packet context */
ipmip6_pkt_context_stop(&ctx->ipmip6, proc);
/* Free all mobile nodes */
ipmip6pm_node_clear(ctx, proc);
/* Stop the current context */
ipmip6_context_stop(&ctx->ipmip6, proc);
ipmip6pm_services_clear(ctx, proc);
#ifdef IPMIP_USE_INET
ipmip_dhcp_context_destroy(&ctx->ipmip6.ipmip, proc);
ipmip_inet_arp_context_destroy(&ctx->ipmip6.ipmip, proc);
#endif
ipmip_dhcp6_context_destroy(&ctx->ipmip6.ipmip, proc);
ipmip6_context_restart_counter_update(&ctx->ipmip6, proc);
ipmip6pm_services_read(ctx, proc);
/* Read configuration */
ipmip6pm_if_configure(ctx, proc);
/**/
ipmip6_context_start(&ctx->ipmip6, proc);
return 0;
}
/*
*===========================================================================
* ipmip6pm_destroy
*===========================================================================
* Description: Shutdown the mobile node portion of the context.
* Parameters: ctx - The MIP6 context.
* Returns:
*
*/
IP_STATIC void
ipmip6pm_context_destroy(Ipmip6pm_context_t *ctx,
Ipmip_proc_t *proc)
{
/* Only if we actually got a context. */
if (ctx != IP_NULL)
{
/* Stop the packet context; for starters */
ipmip6_pkt_context_stop(&ctx->ipmip6, proc);
/* Destroy the entries that has been removed */
ipmip6pm_node_clear(ctx, proc);
/* Stop the rest */
ipmip6_context_stop(&ctx->ipmip6, proc);
/* Remove configuration */
ipmip6pm_if_unconfigure(ctx, proc);
ipmip6pm_services_clear(ctx, proc);
/* Close the IPD */
if (ctx->fd_ipd == IP_INVALID_SOCKET)
(void)ipcom_ipd_init("ipmip6pm", IPCOM_ERR_FAILED, &ctx->fd_ipd);
/**/
ipcom_ipd_exit("ipmip6pm", ctx->fd_ipd);
/**/
ipmip_timer_lock_destroy(&ctx->ipmip6.ipmip, proc, ctx->ifs_lock);
/* Free the lock */
ipmip6pm_route_context_destroy(ctx, proc);
ipmip_context_id_destroy(ctx->idents);
ipmip_context_id_destroy(ctx->bri);
/* Shutdown the 'mip6' context */
ipmip6_context_destroy(&ctx->ipmip6, proc);
}
}
/*
*===========================================================================
* ipmip6pm_context_allocate
*===========================================================================
* Description: Initialize the proxy mobile node portion of the context.
* Parameters: ctx - The MIP6 context.
* Returns:
*
*/
IP_STATIC Ipmip6pm_context_t *
ipmip6pm_context_allocate(Ipmip_proc_t *proc)
{
Ipmip6pm_context_t *ctx = (Ipmip6pm_context_t *)ipmip_context_alloc(proc, sizeof(*ctx), "ipmip6pm", IPMIP6_SYSTEM_PRIORITY, IPMIP6PM_EVENT_BACKLOG);
int f;
/* */
if (ctx == IP_NULL)
return IP_NULL;
/* Initialize */
ipmip6pm_route_context_init(ctx, proc);
/**/
ipcom_atomic_set(&ctx->sequence, ipcom_random());
ipcom_list_init(&ctx->ifs);
ctx->ifs_lock = ipmip_timer_lock_alloc(&ctx->ipmip6.ipmip, proc, IP_NULL, IP_NULL);
ctx->idents = ipmip_context_id_create(ip_offsetof(Ipmip6pm_node_t, identity), 0xFFFFFFFF);
ctx->bri = ipmip_context_id_create(ip_offsetof(Ipmip6pm_br_t, sequence), 0x0000FFFF);
/* Initialize the global information */
if (ipmip6_context_initialize(&ctx->ipmip6,
proc,
&ipmip6pm_ifevent_table) == IP_FALSE)
goto failure;
/* Server side; don't do solicitations */
ctx->ipmip6.iff.no_solicitation = IP_TRUE;
if (ipmip6_pkt_context_create(&ctx->ipmip6,
proc,
&ipmip6pm_dispatch_table,
IPMIP6_DSMIP_UDP_PORT,
(Ipmip_pkt_buf_alloc_t)ipmip6pm_pktbuf_alloc,
(Ipmip_pkt_buf_free_t)ipmip6pm_pktbuf_free) == IP_FALSE)
{
IPCOM_LOG0(ERR, "Unable to create IPMIP6PM Packet Context");
goto failure;
}
ipmip_cli_context_create(&ctx->ipmip6.ipmip,
proc,
"ipmip6pm",
IPCOM_IPD_ID_IPMIP6PM,
(Ipmip_cli_callback_t)ipmip6pm_attr_command);
/* IPD init */
if (ipcom_ipd_init("ipmip6pm", IPCOM_SUCCESS, &ctx->fd_ipd) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "Unable to create IPMIP6PM IPD pipe = %d", ipcom_errno);
goto failure;
}
/* Indicate the elements */
for (f = 0; f < IPMIP6PM_FUNCTION_MAX; f++)
ctx->extensions[f].elem = f;
/* Do service init */
for (f = 0; ipmip6pm_service_registrations[f] != IP_NULL; f++)
(*ipmip6pm_service_registrations[f]) (ctx);
for (f = 0; ipmip6pm_link_registrations[f] != IP_NULL; f++)
(*ipmip6pm_link_registrations[f]) (ctx);
/* Install transport */
ipmip6pm_node_service_install(ctx);
/* Update configuration */
ipmip6pm_update_config(ctx, proc);
/* Return the mobile node instance */
return ctx;
failure:
ipmip6pm_context_destroy(ctx, proc);
return IP_NULL;
}
/*
*===========================================================================
* ipmip6pm_ipd_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
ipmip6pm_ipd_process(Ipmip6pm_context_t *ctx,
Ipmip_proc_t *proc)
{
/* IPD input. */
int event;
Ip_ssize_t len;
Ipmip6pm_pktbuf_t *pbuf = (Ipmip6pm_pktbuf_t *)ipmip_pktbuf_alloc(&ctx->ipmip6.ipmip, proc, 512);
if (pbuf == IP_NULL)
return IP_TRUE;
len = ipcom_ipd_read(ctx->fd_ipd, IPMIP_BUFFER_PTR(&pbuf->ipmip6.ipmip.packet), 512, &event);
if (len < 0)
{
IPCOM_LOG2(ERR, "ipcom_socketread(IPD) failed : %s [%d]",
ipcom_strerror(ipcom_errno), ipcom_errno);
ipmip_util_sock_clear(ctx->fd_ipd);
}
else
{
/* Advance past */
ipmip_buffer_append(&pbuf->ipmip6.ipmip.packet, IP_NULL, len);
switch (event)
{
case IPCOM_IPD_EVENT_RECONFIGURE:
IPCOM_LOG0(INFO, "Received IPD reconfigure message");
ipmip6pm_update_config(ctx, proc);
break;
case IPCOM_IPD_EVENT_KILL:
IPCOM_LOG0(INFO, "Received IPD kill message");
ipmip_pktbuf_release(&ctx->ipmip6.ipmip, proc, &pbuf->ipmip6.ipmip);
return IP_FALSE;
default:
/* Ignore all other IPD messages */
break;
}
}
ipmip_pktbuf_release(&ctx->ipmip6.ipmip, proc, &pbuf->ipmip6.ipmip);
return IP_TRUE;
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void
ipmip6pm_main(void)
{
int num;
int max_fd;
Ipmip6pm_context_t *ctx = IP_NULL;
Ipmip_proc_t *proc;
ipcom_proc_init();
proc = ipmip_proc_alloc();
IPCOM_LOG0(INFO,
"ipmip6pm: starting");
/* Init the configuration */
if (ipmip6pm_configure() != IPCOM_SUCCESS)
goto done;
/* Init IPMIP6MN */
if ((ctx = ipmip6pm_context_allocate(proc)) == IP_NULL)
goto done;
if (ipmip6pm_instances++ == 0)
if (ipmip6pm_init() != IPCOM_SUCCESS)
goto end;
for (;;)
{
Ip_fd_set read_set;
IP_FD_ZERO(&read_set);
/* Set the IPD */
max_fd = ctx->fd_ipd;
IP_FD_SET(ctx->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. */
IPCOM_LOG2(WARNING, "ipcom_socketselect() failed : %s [%d]", ipcom_strerror(ipcom_errno), ipcom_errno);
(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(ctx->fd_ipd, &read_set))
{
if (ipmip6pm_ipd_process(ctx, proc) == IP_FALSE)
goto end;
}
}
}
end:
ipmip6pm_context_destroy(ctx, proc);
/**/
if (--ipmip6pm_instances == 0)
ipmip6pm_exit();
done:
/* Free the context process */
ipmip_proc_destroy(proc);
IPCOM_LOG0(NOTICE,
"ipmip6pm: ending");
ipcom_proc_exit();
}
IP_STATIC Ip_u32
ipmip6pm_context_register_function(Ipmip6pm_context_t *ctx,
Ipmip6pm_extension_t *srv,
Ipmip6pm_function_context_t *func)
{
Ip_u32 type = func->num++;
IPMIP_UNUSED_PARAMETER(ctx);
srv->unique = type;
srv->unique |= func->elem << 16;
func->mask |= (1 << type);
func->functions[type] = srv;
func->node_data += srv->node_data_size;
return srv->unique;
}
IP_GLOBAL Ip_u32
ipmip6pm_context_register_extension(Ipmip6pm_context_t *ctx,
Ipmip6pm_extension_t *srv,
Ip_u32 type)
{
return ipmip6pm_context_register_function(ctx, srv, &ctx->extensions[type]);
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/