/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmippm_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 **************************************************************************** */