658 lines
20 KiB
C
658 lines
20 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6ha_main.c,v $ $Revision: 1.8 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip6ha/src/ipmip6ha_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 "ipmip6ha_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_sysvar.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 "ipmip6ha.h"
|
|
#include "ipmip6ha_h.h"
|
|
#include "ipmip6ha_node.h"
|
|
#include "ipmip6ha_nemo.h"
|
|
#include "ipmip6ha_attr_h.h"
|
|
#include "ipmip6ha_cli.h"
|
|
#include "ipmip6ha_ifevent.h"
|
|
#include "ipmip6ha_mh.h"
|
|
#include "ipmip6ha_icmp.h"
|
|
#include "ipmip6ha_if.h"
|
|
#include "ipmip6ha_route.h"
|
|
#include "ipmip6ha_pktbuf.h"
|
|
#include "ipmip6ha_mag.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
IP_PUBLIC Ip_err ipmip6ha_exit(void);
|
|
IP_PUBLIC Ip_err ipmip6ha_init(void);
|
|
IP_PUBLIC Ip_err ipmip6ha_start(void);
|
|
IP_PUBLIC const char *ipmip6ha_version(void);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
static int ipmip6ha_instances = 0;
|
|
|
|
/* Dispatch function callbacks */
|
|
static Ipmip6_pkt_context_dispatch_t ipmip6ha_dispatch_table =
|
|
{
|
|
(Ipmip6_pkt_dispatch_t)ipmip6ha_mh_dispatch,
|
|
(Ipmip6_pkt_dispatch_t)ipmip6ha_icmp_dispatch
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC unsigned
|
|
ipmip6ha_relay_nai_obj_hash(Ipmip6ha_relay_key_t *obj)
|
|
{
|
|
return ipcom_hash_update(obj->nai, (int)obj->nai_len, 0);
|
|
}
|
|
|
|
IP_STATIC Ip_bool
|
|
ipmip6ha_relay_nai_key_cmp(Ipmip6ha_relay_key_t *obj,
|
|
Ipmip6ha_relay_key_t *key)
|
|
{
|
|
/**/
|
|
return ipmip_util_strnncmp(obj->nai, obj->nai_len, key->nai, key->nai_len);
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_relay_map_sysvar_nai_foreach(struct Ipmip_proc *proc,
|
|
char *name,
|
|
char *subkey,
|
|
const char *value,
|
|
Ipmip6ha_context_t *ctx)
|
|
{
|
|
Ipmip6ha_relay_key_t *nkey;
|
|
Ip_size_t slen = ipcom_strlen(subkey);
|
|
Ipmip6ha_if_t *ifp = ipmip6ha_if_findbyname(ctx, proc, value);
|
|
|
|
|
|
if (ifp == IP_NULL)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"Unable to allocate to MAP %s to %s -- no such interface",
|
|
subkey, value));
|
|
return;
|
|
}
|
|
|
|
IPMIP_UNUSED_PARAMETER(name);
|
|
|
|
nkey = ipcom_calloc(1, sizeof(*nkey) + slen + 1);
|
|
if (!nkey)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"Unable to allocate NAI entry"));
|
|
return;
|
|
}
|
|
|
|
nkey->nai = (char *)(nkey + 1);
|
|
ipcom_strcpy(nkey->nai, subkey);
|
|
nkey->nai_len = slen;
|
|
nkey->ifp = ifp;
|
|
|
|
/* Overload? */
|
|
ipcom_hash_add(ctx->relay_map, nkey);
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_configure_relay_map(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
ipmip_sysvar_foreach(proc,
|
|
(Ipmip_sysvar_foreach_t) ipmip6ha_relay_map_sysvar_nai_foreach,
|
|
ctx,
|
|
"ipmip6ha.relay_map.*");
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_unconfigure_relay_map_cb(Ipmip6ha_relay_key_t *obj,
|
|
Ipcom_hash *htable)
|
|
{
|
|
ipcom_hash_remove(htable, obj);
|
|
ipcom_free(obj);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_unconfigure_relay_map(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
ipcom_hash_for_each(ctx->relay_map, (Ipcom_hash_foreach_cb_func)ipmip6ha_unconfigure_relay_map_cb, ctx->relay_map);
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_dump_relay_map_cb(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6ha_relay_key_t *obj,
|
|
Ipmip_buffer_t *buffer,
|
|
void *unused)
|
|
{
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(unused);
|
|
|
|
ipmip_cli_config_printf(buffer,
|
|
"ipmip6ha.relay_map.%s=%s",
|
|
obj->nai, obj->ifp->ipmip6.iff.ifname);
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_services_clear(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
unsigned si;
|
|
|
|
for (si = 0; si < ctx->extensions_num; si++)
|
|
{
|
|
if (ctx->extensions[si]->config_global != IP_NULL && ctx->extdata[si] != IP_NULL)
|
|
{
|
|
(*ctx->extensions[si]->config_global) (ctx, proc, IPMIP_CALLBACK_CONFIG_FREE, ctx->extdata[si], IP_NULL);
|
|
ipcom_free(ctx->extdata[si]);
|
|
ctx->extdata[si] = IP_NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6ha_services_read(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
unsigned si;
|
|
|
|
for (si = 0; si < ctx->extensions_num; si++)
|
|
{
|
|
if (ctx->extensions[si]->config_global != IP_NULL && ctx->extensions[si]->global_data_size)
|
|
{
|
|
ctx->extdata[si] = ipcom_calloc(1, ctx->extensions[si]->global_data_size);
|
|
(*ctx->extensions[si]->config_global) (ctx, proc, IPMIP_CALLBACK_CONFIG_READ, ctx->extdata[si], 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
|
|
ipmip6ha_update_config(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
ipmip6_pkt_context_stop(&ctx->ipmip6, proc);
|
|
|
|
/* Free all mobile nodes */
|
|
ipmip6ha_node_clear(ctx, proc);
|
|
|
|
/* Stop the current context */
|
|
ipmip6_context_stop(&ctx->ipmip6, proc);
|
|
|
|
/* Clear global service config */
|
|
ipmip6ha_services_clear(ctx, proc);
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
ipmip_dhcp_context_destroy(&ctx->ipmip6.ipmip, proc);
|
|
#endif
|
|
|
|
ipmip6ha_unconfigure_relay_map(ctx, proc);
|
|
|
|
/* Unconfigure IF */
|
|
ipmip6ha_if_unconfigure(ctx, proc);
|
|
|
|
/* Restart Counter */
|
|
ipmip6_context_restart_counter_update(&ctx->ipmip6, proc);
|
|
|
|
/* Clear global service config */
|
|
ipmip6ha_services_read(ctx, proc);
|
|
|
|
if (ctx->prefixes != IP_NULL)
|
|
ipcom_route_free_table(ctx->prefixes);
|
|
|
|
ctx->prefixes = ipcom_route_new_table(sizeof(struct Ip_in6_addr) * 8,
|
|
(Ipcom_route_notify_func) ipmip_route_notify);
|
|
|
|
/* Re-read them */
|
|
ipmip6ha_if_configure(ctx, proc);
|
|
|
|
/* Configure relay map */
|
|
ipmip6ha_configure_relay_map(ctx, proc);
|
|
|
|
/**/
|
|
ipmip6_context_start(&ctx->ipmip6, proc);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_destroy
|
|
*===========================================================================
|
|
* Description: Shutdown the mobile node portion of the context.
|
|
* Parameters: ctx - The MIP6 context.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6ha_context_destroy(Ipmip6ha_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 */
|
|
ipmip6ha_node_clear(ctx, proc);
|
|
|
|
/* Stop the rest */
|
|
ipmip6_context_stop(&ctx->ipmip6, proc);
|
|
|
|
/**/
|
|
ipmip6ha_unconfigure_relay_map(ctx, proc);
|
|
ipmip6ha_if_unconfigure(ctx, proc);
|
|
ipmip6ha_nemo_unconfigure(ctx, proc, ctx->nemo);
|
|
ipmip6ha_services_clear(ctx, proc);
|
|
|
|
/* Close the IPD */
|
|
if (ctx->fd_ipd == IP_INVALID_SOCKET)
|
|
(void)ipcom_ipd_init("ipmip6ha", IPCOM_ERR_FAILED, &ctx->fd_ipd);
|
|
|
|
ipcom_hash_delete(ctx->relay_map);
|
|
|
|
/**/
|
|
ipcom_ipd_exit("ipmip6ha", ctx->fd_ipd);
|
|
|
|
/**/
|
|
ipmip_timer_lock_destroy(&ctx->ipmip6.ipmip, proc, ctx->ifs_lock);
|
|
|
|
/* Free the lock */
|
|
ipmip6ha_nemo_context_destroy(ctx, proc);
|
|
|
|
ipcom_mutex_delete(&ctx->prefixes_lock);
|
|
|
|
ipmip6ha_route_context_destroy(ctx, proc);
|
|
|
|
/* Free the identity contexts */
|
|
ipmip_context_id_destroy(ctx->idents);
|
|
ipmip_context_id_destroy(ctx->bri);
|
|
|
|
/* Shutdown the 'mip6' context */
|
|
ipmip6_context_destroy(&ctx->ipmip6, proc);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6ha_context_allocate
|
|
*===========================================================================
|
|
* Description: Initialize the mobile node portion of the context.
|
|
* Parameters: ctx - The MIP6 context.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipmip6ha_context_t *
|
|
ipmip6ha_context_allocate(Ipmip_proc_t *proc)
|
|
{
|
|
Ipmip6ha_context_t *ctx = (Ipmip6ha_context_t *)ipmip_context_alloc(proc, sizeof(*ctx), "ipmip6ha", IPMIP6_SYSTEM_PRIORITY, IPMIP6HA_EVENT_BACKLOG);
|
|
int i;
|
|
|
|
/* */
|
|
if (ctx == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
/* For LAS */
|
|
ipmip_dhcp6_embedded_server_init(&ctx->ipmip6.ipmip, proc);
|
|
|
|
ipmip6ha_route_context_init(ctx, proc);
|
|
|
|
/* Initialize */
|
|
ipmip6ha_nemo_context_init(ctx, proc);
|
|
|
|
ipcom_list_init(&ctx->ifs);
|
|
|
|
ipcom_mutex_create(&ctx->prefixes_lock);
|
|
|
|
ctx->ifs_lock = ipmip_timer_lock_alloc(&ctx->ipmip6.ipmip, proc, IP_NULL, IP_NULL);
|
|
|
|
ctx->idents = ipmip_context_id_create(ip_offsetof(Ipmip6ha_node_t, identity), 0xFFFFFFFF);
|
|
ctx->bri = ipmip_context_id_create(ip_offsetof(Ipmip6ha_br_t, sequence), 0x0000FFFF);
|
|
|
|
/* Initialize the global information */
|
|
if (ipmip6_context_initialize(&ctx->ipmip6,
|
|
proc,
|
|
&ipmip6ha_ifevent_table) == IP_FALSE)
|
|
goto failure;
|
|
|
|
/* Server side; don't do solicitations */
|
|
ctx->ipmip6.iff.no_solicitation = IP_TRUE;
|
|
|
|
/**/
|
|
ctx->relay_map = ipcom_hash_new((Ipcom_hash_obj_func) ipmip6ha_relay_nai_obj_hash,
|
|
(Ipcom_hash_key_func) ipmip6ha_relay_nai_obj_hash,
|
|
(Ipcom_hash_cmp_func) ipmip6ha_relay_nai_key_cmp);
|
|
|
|
if (ipmip6_pkt_context_create(&ctx->ipmip6,
|
|
proc,
|
|
&ipmip6ha_dispatch_table,
|
|
IPMIP6_DSMIP_UDP_PORT,
|
|
(Ipmip_pkt_buf_alloc_t)ipmip6ha_pktbuf_alloc,
|
|
(Ipmip_pkt_buf_free_t)ipmip6ha_pktbuf_free) == IP_FALSE)
|
|
{
|
|
IPCOM_LOG0(ERR, "Unable to create IPMIP6HA Packet Context");
|
|
goto failure;
|
|
}
|
|
|
|
ipmip_cli_context_create(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"ipmip6ha",
|
|
IPCOM_IPD_ID_IPMIP6HA,
|
|
(Ipmip_cli_callback_t)ipmip6ha_attr_command);
|
|
|
|
/* IPD init */
|
|
if (ipcom_ipd_init("ipmip6ha", IPCOM_SUCCESS, &ctx->fd_ipd) != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG1(ERR, "Unable to create IPMIP6MN IPD pipe = %d", ipcom_errno);
|
|
goto failure;
|
|
}
|
|
|
|
(void) ipcom_inet_pton(IP_AF_INET6, "FE80::", &ctx->link_local_prefix);
|
|
|
|
|
|
for (i = 0; ipmip6ha_service_registrations[i] != IP_NULL; i++)
|
|
(*ipmip6ha_service_registrations[i]) (ctx);
|
|
|
|
/* Update configuration */
|
|
ipmip6ha_update_config(ctx, proc);
|
|
|
|
/* Return the mobile node instance */
|
|
return ctx;
|
|
|
|
failure:
|
|
ipmip6ha_context_destroy(ctx, 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
|
|
ipmip6ha_ipd_process(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc)
|
|
{
|
|
/* IPD input. */
|
|
int event;
|
|
Ip_ssize_t len;
|
|
Ipmip6ha_pktbuf_t *pbuf = (Ipmip6ha_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, (Ip_size_t)len);
|
|
|
|
switch (event)
|
|
{
|
|
case IPCOM_IPD_EVENT_RECONFIGURE:
|
|
IPCOM_LOG0(INFO, "Received IPD reconfigure message");
|
|
ipmip6ha_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
|
|
ipmip6ha_main(void)
|
|
{
|
|
int num;
|
|
int max_fd;
|
|
Ipmip6ha_context_t *ctx = IP_NULL;
|
|
Ipmip_proc_t *proc;
|
|
|
|
ipcom_proc_init();
|
|
|
|
proc = ipmip_proc_alloc();
|
|
|
|
IPCOM_LOG0(INFO,
|
|
"ipmip6ha: starting");
|
|
|
|
/* Init the configuration */
|
|
if (ipmip6ha_configure() != IPCOM_SUCCESS)
|
|
goto done;
|
|
|
|
/* Init IPMIP6MN */
|
|
if ((ctx = ipmip6ha_context_allocate(proc)) == IP_NULL)
|
|
goto done;
|
|
|
|
if (ipmip6ha_instances++ == 0)
|
|
if (ipmip6ha_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 (ipmip6ha_ipd_process(ctx, proc) == IP_FALSE)
|
|
goto end;
|
|
}
|
|
}
|
|
}
|
|
|
|
end:
|
|
ipmip6ha_context_destroy(ctx, proc);
|
|
|
|
/**/
|
|
if (--ipmip6ha_instances == 0)
|
|
ipmip6ha_exit();
|
|
|
|
|
|
done:
|
|
/* Free the context process */
|
|
ipmip_proc_destroy(proc);
|
|
|
|
IPCOM_LOG0(NOTICE,
|
|
"ipmip6ha: ending");
|
|
|
|
ipcom_proc_exit();
|
|
}
|
|
|
|
|
|
IP_GLOBAL Ip_u32
|
|
ipmip6ha_context_register_extension(Ipmip6ha_context_t *ctx,
|
|
Ipmip6ha_extension_t *srv,
|
|
Ip_bool reg_H,
|
|
Ip_bool reg_P)
|
|
{
|
|
srv->type = ctx->extensions_num++;
|
|
ctx->extensions[srv->type] = srv;
|
|
|
|
if (reg_H)
|
|
{
|
|
ctx->extensions_H_mask |= (1 << srv->type);
|
|
ctx->extensions_node_H_data += srv->node_data_size;
|
|
}
|
|
|
|
if (reg_P)
|
|
{
|
|
ctx->extensions_P_mask |= (1 << srv->type);
|
|
ctx->extensions_node_P_data += srv->node_data_size;
|
|
}
|
|
|
|
return srv->type;
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip6ha_dump_relay_map(Ipmip6ha_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip_buffer_t *buffer)
|
|
{
|
|
ipmip_util_hash_foreach(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
ctx->relay_map,
|
|
(Ipmip_util_hash_foreach_t)ipmip6ha_dump_relay_map_cb,
|
|
buffer,
|
|
IP_NULL);
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|