Files
m241Neelima/components/ip_net2-6.9/ipmippm/config/ipmippm_pmipv4.c
T
2026-07-30 11:19:44 +05:30

497 lines
21 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmippm_pmipv4.c,v $ $Revision: 1.6 $
* $Source: /home/interpeak/CVSRoot/ipmippm/config/ipmippm_pmipv4.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 "ipmippm_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#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_hash.h>
#include <ipcom_err.h>
#include <ipcom_sysvar.h>
#include <ipcom_syslog.h>
#include <ipcom_shell.h>
#include <ipcom_route.h>
#include <ipnet.h>
#include <ipnet_radvd.h>
#include <ipmip.h>
#include <private/ipmip_util.h>
#include <private/ipmip_sysvar.h>
#include <private/ipmip_inet.h>
#include <ipmip4.h>
#include <private/ipmip4_context.h>
#include <private/ipmip4_util.h>
#include <private/ipmip4_sysext.h>
#include <private/ipmip4_pkt.h>
#include "ipmippm.h"
#include "ipmippm_h.h"
#include "ipmippm_attr_h.h"
#include "ipmippm_pktbuf.h"
#include "ipmippm_if.h"
#include "ipmippm_client.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIPPM_PMIPV4_SERVICE "PMIPv4-UDP"
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipmippm_pmipv4_config_instance
{
Ipmip4_pkt_udp_register_t udpr;
Ip_u16 port;
struct Ip_sockaddr_in sin4;
struct Ipmippm_client_conf *conf;
} Ipmippm_pmipv4_config_instance_t;
typedef struct Ipmippm_pmipv4_output
{
struct Ip_sockaddr_in dst_output;
Ipmippm_pmipv4_config_instance_t *inst_config;
} Ipmippm_pmipv4_output_t;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ipmipmn_api_extension_t ipmippm_pmipv4_srv;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
IP_STATIC int
ipmippm_pmipv4_reg_output_send(Ipmippm_context_t *data,
Ipmip_proc_t *proc,
Ipmippm_client_t *node,
Ipmippm_pktbuf_t *pbuf,
struct Ipmipmn_api_coa *coa,
Ip_bool deregister,
Ip_u32 src,
Ip_u32 dst,
Ipmippm_pmipv4_output_t *s_output)
{
Ipmip_buffer_t prrp;
Ip_size_t rhdr;
IPMIP_UNUSED_PARAMETER(deregister);
IPMIP_UNUSED_PARAMETER(src);
IPMIP_UNUSED_PARAMETER(dst);
IPMIP_UNUSED_PARAMETER(coa);
ipmip_buffer_init(&prrp);
rhdr = ipmip_attr_hdr_req_create(&prrp, 0, 0, IPMIP4_CLI_PMIPV4_PRRQ);
ipmip_attr_put(&prrp, IPMIP4_CLI_PMIPV4_ATTR_MESSAGE, IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet), IPMIP_BUFFER_DATA(&pbuf->api.ipmip4.ipmip.packet));
ipmip_attr_hdr_finalize(&prrp, rhdr);
if (ipcom_sendto(s_output->inst_config->udpr.fd, IPMIP_BUFFER_DATA(&prrp), IPMIP_BUFFER_SIZE(&prrp), 0, (struct Ip_sockaddr *)&s_output->dst_output, sizeof(s_output->dst_output)) < 0)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->api.ipmip4.ipmip,
proc,
"%s unable to write request errno=%d",
IPMIPMN_API_NODE_NAME(&data->api, proc, &node->api),
ipcom_errno));
ipmip_buffer_release(&prrp);
return -1;
}
ipmip_buffer_release(&prrp);
return 0;
}
IP_STATIC void
ipmippm_pmipv4_trigger_complete(Ipmippm_context_t *data,
Ipmip_proc_t *proc,
Ipmippm_client_t *node,
Ipmippm_pktbuf_t *pbuf,
Ip_u8 status)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&pbuf->api.ipmip4.ipmip.packet);
Ipmippm_pmipv4_config_instance_t *conf = pbuf->trigger.pmTriggerCompletionData;
Ip_size_t rhdr;
Ipmip_buffer_t trigger;
ipmip_buffer_init(&trigger);
rhdr = ipmip_attr_hdr_err(&trigger, hdr, status, IP_NULL);
if (node != IP_NULL)
{
if (node->api.params.mnRegCoA)
ipmip_attr_put_inet(&trigger, IPMIP4_CLI_PMIPV4_ATTR_NFA_COA, node->api.params.mnRegCoA->addr);
ipmip_attr_put_inet(&trigger, IPMIP4_CLI_PMIPV4_ATTR_HOA, node->api.params.assigned_home_address);
ipmip_attr_put_inet(&trigger, IPMIP4_CLI_PMIPV4_ATTR_HA, node->api.params.assigned_home_agent);
ipmip_attr_put(&trigger, IPMIP4_CLI_PMIPV4_ATTR_MN_NAI, IPMIP4_MSGEXT_SHDR_EXT_SIZE(node->api.params.nai_mn), IPMIP4_MSGEXT_SHDR_EXT_DATA(node->api.params.nai_mn));
ipmip_attr_put_u32(&trigger, IPMIP4_CLI_PMIPV4_ATTR_HA, node->api.params.assigned_home_agent);
ipmip_attr_put_u32(&trigger, IPMIP4_CLI_PMIPV4_ATTR_LIFETIME, node->api.params.mnRegTimeGranted);
}
ipmip_attr_hdr_finalize(&trigger, rhdr);
if (ipcom_sendto(conf->udpr.fd, IPMIP_BUFFER_DATA(&trigger), IPMIP_BUFFER_SIZE(&trigger), 0, (struct Ip_sockaddr *)pbuf->api.ipmip4.ipmip.srcinfo.src, sizeof(struct Ip_sockaddr_in)) < 0)
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&data->api.ipmip4.ipmip,
proc,
"%s unable to write request errno=%d",
IPMIPMN_API_NODE_NAME(&data->api, proc, &node->api),
ipcom_errno));
}
/* Remove the reference */
ipmip_buffer_release(&trigger);
ipmip_pktbuf_release(&data->api.ipmip4.ipmip, proc, &pbuf->api.ipmip4.ipmip);
}
IP_STATIC void
ipmippm_pmipv4_req_mobile_home(struct Ipmippm_context *ctx,
struct Ipmip_proc *proc,
struct Ipmippm_client_conf *conf,
Ipmippm_pmipv4_config_instance_t *inst_config,
void *node_config,
struct Ipmippm_client *node,
Ip_bool deregister,
struct Ipmippm_pktbuf *pbuf)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(conf);
IPMIP_UNUSED_PARAMETER(deregister);
IPMIP_UNUSED_PARAMETER(node_config);
IPMIP_UNUSED_PARAMETER(inst_config);
IPMIP_UNUSED_PARAMETER(node);
IPMIP_UNUSED_PARAMETER(pbuf);
}
IP_STATIC void
ipmippm_pmipv4_req_mobile_foreign(struct Ipmippm_context *ctx,
struct Ipmip_proc *proc,
struct Ipmippm_client_conf *conf,
Ipmippm_pmipv4_config_instance_t *inst_config,
void *node_config,
struct Ipmippm_client *node,
Ip_bool deregister,
struct Ipmippm_pktbuf *pbuf)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(conf);
IPMIP_UNUSED_PARAMETER(deregister);
IPMIP_UNUSED_PARAMETER(node_config);
IPMIP_UNUSED_PARAMETER(inst_config);
if (node->pmAccessType)
ipmip4_msgext_buffer_append_shdr(&pbuf->api.ipmip4.ipmip.packet, node->pmAccessType);
if (node->pmDeviceID)
ipmip4_msgext_buffer_append_shdr(&pbuf->api.ipmip4.ipmip.packet, node->pmDeviceID);
if (node->pmInterfaceID)
ipmip4_msgext_buffer_append_shdr(&pbuf->api.ipmip4.ipmip.packet, node->pmInterfaceID);
if (node->pmSubscriberID)
ipmip4_msgext_buffer_append_shdr(&pbuf->api.ipmip4.ipmip.packet, node->pmSubscriberID);
if (node->pmPerNodeAuthMethod)
ipmip4_msgext_buffer_append_lhdr(&pbuf->api.ipmip4.ipmip.packet, node->pmPerNodeAuthMethod);
}
IP_STATIC void
ipmippm_pmipv4_udp_prtrigger(Ipmippm_context_t *ctx,
Ipmip_proc_t *proc,
Ipmippm_pmipv4_config_instance_t *conf,
Ipmippm_pktbuf_t *pbuf)
{
Ipmippm_pmipv4_output_t s_output;
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&pbuf->api.ipmip4.ipmip.packet);
ipmip_attr_hdr_parse(IPMIP4_CLI_PMIPV4_ATTR_MAX, hdr, pbuf->trigger.pmTriggerAttr);
pbuf->trigger.pmTriggerType = IPMIP_ATTR_HDR_TYPE(hdr);
/**/
pbuf->api.iff.priv = conf->conf->iff;
ipcom_memcpy(&s_output.dst_output, &pbuf->api.ipmip4.ipmip.srcinfo.src->sin, sizeof(s_output.dst_output));
s_output.inst_config = conf;
pbuf->trigger.pmTriggerCOAOutput = (Ipmipmn_api_coa_output_t)ipmippm_pmipv4_reg_output_send;
pbuf->trigger.pmTriggerCOAOutputAuxData = &s_output;
pbuf->trigger.pmTriggerCOAOutputAuxSize = sizeof(s_output);
pbuf->trigger.pmTriggerCompletion = (Ipmippm_pktbuf_trigger_complete_t)ipmippm_pmipv4_trigger_complete;
pbuf->trigger.pmTriggerCompletionData = conf;
/* Need to do lookup */
ipmippm_client_trigger_handoff(ctx, proc, pbuf);
return;
}
IP_STATIC void
ipmippm_pmipv4_udp_prrq(Ipmippm_context_t *ctx,
Ipmip_proc_t *proc,
Ipmippm_pmipv4_config_instance_t *conf,
Ipmippm_pktbuf_t *pbuf)
{
Ipmip_buffer_t prrq;
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&pbuf->api.ipmip4.ipmip.packet);
ipmip_attr_hdr_parse(IPMIP4_CLI_PMIPV4_ATTR_MAX, hdr, pbuf->trigger.pmTriggerAttr);
/**/
pbuf->api.iff.priv = conf->conf->iff;
/**/
if (pbuf->trigger.pmTriggerAttr[IPMIP4_CLI_PMIPV4_ATTR_MESSAGE] == IP_NULL)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Received PMIPv4 PRRQ -- missing message"));
goto done_out;
}
ipmip_buffer_init(&prrq);
ipmip_buffer_append(&prrq, IPMIP_ATTR_DATA(pbuf->trigger.pmTriggerAttr[IPMIP4_CLI_PMIPV4_ATTR_MESSAGE]), IPMIP_ATTR_PAYLOAD(pbuf->trigger.pmTriggerAttr[IPMIP4_CLI_PMIPV4_ATTR_MESSAGE]));
ipmip_buffer_assign(&pbuf->api.ipmip4.ipmip.packet, &prrq);
ipmipmn_api_reg_recv(&ctx->api, proc, &pbuf->api);
return;
done_out:
ipmip_pktbuf_release(&ctx->api.ipmip4.ipmip, proc, &pbuf->api.ipmip4.ipmip);
}
IP_STATIC void
ipmippm_pmipv4_udp_recvmsg(Ipmippm_context_t *ctx,
Ipmip_proc_t *proc,
Ipmippm_pktbuf_t *pbuf,
Ipmippm_pmipv4_config_instance_t *conf)
{
struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&pbuf->api.ipmip4.ipmip.packet);
if (IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet) < sizeof(struct Ipmip_attr_header))
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Received PMIPv4 Trigger Message -- Truncated"));
goto done_out;
}
switch (IPMIP_ATTR_HDR_TYPE(hdr))
{
case IPMIP4_CLI_PMIPV4_PREVRQ:
IPMIP4_EVENT_IF(INFO, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Received PMIPv4 PREVRQ"));
ipmippm_pmipv4_udp_prtrigger(ctx, proc, conf, pbuf);
return;
case IPMIP4_CLI_PMIPV4_PTRQ:
IPMIP4_EVENT_IF(INFO, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Received PMIPv4 PTRQ"));
ipmippm_pmipv4_udp_prtrigger(ctx, proc, conf, pbuf);
return;
case IPMIP4_CLI_PMIPV4_PRRQ:
IPMIP4_EVENT_IF(INFO, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Received PMIPv4 PRRQ"));
ipmippm_pmipv4_udp_prrq(ctx, proc, conf, pbuf);
return;
}
done_out:
ipmip_pktbuf_release(&ctx->api.ipmip4.ipmip, proc, &pbuf->api.ipmip4.ipmip);
}
IP_STATIC void
ipmippm_pmipv4_config(struct Ipmippm_context *ctx,
struct Ipmip_proc *proc,
int action,
const char *pre,
const char *spec,
struct Ipmippm_client_conf *conf,
Ipmippm_pmipv4_config_instance_t *inst_config,
Ipmip_cli_message_t *request)
{
IPMIP_UNUSED_PARAMETER(ctx);
IPMIP_UNUSED_PARAMETER(proc);
IPMIP_UNUSED_PARAMETER(conf);
IPMIP_UNUSED_PARAMETER(request);
IPMIP_UNUSED_PARAMETER(pre);
IPMIP_UNUSED_PARAMETER(spec);
if (action == IPMIP_CALLBACK_CONFIG_READ)
{
inst_config->udpr.fd = IP_INVALID_SOCKET;
if (ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "%s.pmipv4.dhcp.enable", pre), "%s.%spmipv4.dhcp.enable", pre, spec))
{
inst_config->port = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(IPMIP4_PORT, "%s.pmipv4.dhcp.port", pre), "%s.%spmipv4.dhcp.port", pre, spec);
ipcom_memset(&inst_config->sin4, 0, sizeof(inst_config->sin4));
inst_config->sin4.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&inst_config->sin4, sizeof(inst_config->sin4));
inst_config->sin4.sin_port = ip_htons(inst_config->port);
inst_config->sin4.sin_addr.s_addr = conf->iff->iff.ifaddr;
inst_config->udpr.fd = ipmip_inet_udp_socket(&inst_config->sin4);
if (inst_config->udpr.fd != IP_INVALID_SOCKET)
{
inst_config->udpr.udp_callback = (Ipmip4_pkt_udp_cb_t)ipmippm_pmipv4_udp_recvmsg;
inst_config->udpr.opaque = inst_config;
/* Start the process */
inst_config->conf = conf;
/**/
ipmip4_pkt_udp_register(&ctx->api.ipmip4, proc, &inst_config->udpr);
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Created PMIPv4 UDP socket for %s %s:%u",
inst_config->conf->iff->iff.ipmip.ifname,
ipmip_ntop_inet(proc, inst_config->conf->iff->iff.ifaddr),
inst_config->port));
}
else
{
IPMIP4_EVENT_IF(WARNING, proc,
ipmip_log_event_add(&ctx->api.ipmip4.ipmip,
proc,
"Unable to create PMIPv4 UDP socket for %s %s:%u",
inst_config->conf->iff->iff.ipmip.ifname,
ipmip_ntop_inet(proc, inst_config->conf->iff->iff.ifaddr),
inst_config->port));
}
}
}
else if (action == IPMIP_CALLBACK_CONFIG_FREE)
{
ipmip4_pkt_udp_unregister(&ctx->api.ipmip4, proc, &inst_config->udpr);
if (inst_config->udpr.fd != IP_INVALID_SOCKET)
ipcom_socketclose(inst_config->udpr.fd);
/* Clear */
inst_config->udpr.fd = IP_INVALID_SOCKET;
}
else if (action == IPMIP_CALLBACK_CONFIG_DUMP)
{
/* Could dump, but dont bother */
if (inst_config->udpr.fd != IP_INVALID_SOCKET)
{
ipmip_cli_config_printf(&request->message,
"%s.%spmipv4.dhcp.enable=enabled",
pre, spec);
ipmip_cli_config_printf(&request->message,
"%s.%spmipv4.dhcp.port=%u",
pre, spec, inst_config->port);
}
else
{
ipmip_cli_config_printf(&request->message,
"%s.%spmipv4.dhcp.enable=disabled",
pre, spec);
}
}
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL void ipmippm_pmipv4_install(void);
IP_GLOBAL void
ipmippm_pmipv4_install(void)
{
ipcom_memset(&ipmippm_pmipv4_srv, 0, sizeof(ipmippm_pmipv4_srv));
ipmippm_pmipv4_srv.name = IPMIPPM_PMIPV4_SERVICE;
ipmippm_pmipv4_srv.instance_data_size = sizeof(Ipmippm_pmipv4_config_instance_t);
ipmippm_pmipv4_srv.config_instance = (Ipmipmn_api_extension_config_instance_t)ipmippm_pmipv4_config;
ipmippm_pmipv4_srv.pkt_req_mobile_home = (Ipmipmn_api_extension_pkt_req_mobile_home_t)ipmippm_pmipv4_req_mobile_home;
ipmippm_pmipv4_srv.pkt_req_mobile_foreign = (Ipmipmn_api_extension_pkt_req_mobile_foreign_t)ipmippm_pmipv4_req_mobile_foreign;
ipmippm_context_register_function(&ipmippm_pmipv4_srv);
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/