/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipmn_icmp.c,v $ $Revision: 1.6 $ * $Source: /home/interpeak/CVSRoot/ipmipmn/src/ipmipmn_icmp.c,v $ * $Author: jhorteli $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmipmn_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 "ipmipmn_h.h" #include "ipmipmn_if.h" #include "ipmipmn_pktbuf.h" #include "ipmipmn_icmp.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipmn_icmp_input *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipmipmn_icmp_input(Ipmipmn_context_t *data, Ipmip_proc_t *proc, Ipmipmn_pktbuf_t *pbuf) { Ipmip4_icmp_advert_t *pkt; int ret; Ipmip4_icmp_ext_advert_t *extadv; /* Too short packet */ if (IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet) < sizeof(Ipmip4_icmp_advert_t)) { IPCOM_LOG2(WARNING, "ADV ipcom_recvmsg() failed from '%s', short packet [length = %d]", ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src), IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet)); return; } /* We only listen on ICMP agent advertisements */ pkt = IPMIP_BUFFER_PTR(&pbuf->api.ipmip4.ipmip.packet); /* Sanity */ if (pkt->adv_num_addrs > 0 && pkt->adv_addr_entry_size < 2) { IPCOM_LOG2(WARNING, "ADV ipcom_recvmsg() failed from '%s', short addr/pref [length = %d]", ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src), pkt->adv_addr_entry_size); return; } ret = sizeof(Ipmip4_icmp_advert_t) + (pkt->adv_num_addrs * pkt->adv_addr_entry_size * 4); /* Too short packet */ if (IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet) < (unsigned)ret) { IPCOM_LOG2(WARNING, "ADV ipcom_recvmsg() failed from '%s', short packet [length = %d]", ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src), IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet)); return; } /* Parse the message block */ ret = ipmip4_msgext_icmp_parse(proc, pbuf->api.iff.pub->ipmip.ifname, pbuf->api.ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr, &pbuf->api.ipmip4.ext.icmp, ipmip_buffer_offset(&pbuf->api.ipmip4.ipmip.packet, ret), IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet) - ret); /* Did the parse succeed? */ if (ret != IPMIP4_REG_EXT_SUCCESS) return; /* Is it a mobility advertisement? */ if (pbuf->api.ipmip4.ext.icmp.agent == IP_NULL) return; /* Retrieve the mobility advertisement */ extadv = (Ipmip4_icmp_ext_advert_t *) pbuf->api.ipmip4.ext.icmp.agent; /* Extract the advertised lifetime and flags */ pbuf->api.advinfo.lifetime = IP_GET_NTOHS(&extadv->reg_lifetime); pbuf->api.advinfo.flags = IP_GET_NTOHS(&extadv->flags); pbuf->api.advinfo.adv_seq = IP_GET_NTOHS(&extadv->seq); /*********** FOREIGN AGENT ADVERTISEMENT ***********/ if (IP_BIT_ISTRUE(pbuf->api.advinfo.flags, IPMIP4_ICMP_ADVEXT_FLAG_FOREIGN_AGENT)) { /* An FA agent adv is required to include at least one c/o-address */ if (IPMIP4_MSGEXT_SHDR_EXT_SIZE(extadv) < 10) { IPCOM_LOG1(WARNING, "missing c/o address from '%s' FA", ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src)); return; } pbuf->api.advinfo.coa = IP_GET_32ON8(&extadv->coa[0]); IPCOM_LOG4(DEBUG, "received FA %sRtAdv #%d from '%s' [c/o=%s]", pbuf->api.ipmip4.ext.icmp.lla.found > 0? "Pr" : "", pbuf->api.advinfo.adv_seq, ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src), ipmip_ntop_inet(proc, pbuf->api.advinfo.coa)); /* Lookup and init FA */ ipmipmn_if_fa_adv(data, proc, pbuf); } /*********** HOME AGENT ADVERTISEMENT ***********/ else if (IP_BIT_ISTRUE(pbuf->api.advinfo.flags, IPMIP4_ICMP_ADVEXT_FLAG_HOME_AGENT)) { IPCOM_LOG2(DEBUG, "received HA RtAdv #%d from '%s'", pbuf->api.advinfo.adv_seq, ipmip_ntop_sa(proc, pbuf->api.ipmip4.ipmip.srcinfo.src)); /* Lookup and init FA */ ipmipmn_if_ha_adv(data, proc, pbuf); } return; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipmn_icmp_recv *=========================================================================== * Description: Handles incoming advertisements or solicitations * Parameters: data - Context * proc - Current process. * pbuf - Packet buffer * Returns: * */ IP_GLOBAL void ipmipmn_icmp_recv(struct Ipmipmn_context *data, struct Ipmip_proc *proc, Ipmipmn_pktbuf_t *pbuf) { if (pbuf->api.ipmip4.ipmip.srcinfo.lladdr != IP_NULL) { Ipcom_icmp_header *icmph = IPMIP_BUFFER_PTR(&pbuf->api.ipmip4.ipmip.packet); /* Truncated packet? */ if (IPMIP_BUFFER_SIZE(&pbuf->api.ipmip4.ipmip.packet) < IPCOM_ICMP_HEADER_LENGTH) goto done_out; if ((pbuf->api.iff.priv = ipmipmn_if_findbyindex(data, proc, pbuf->api.ipmip4.ipmip.srcinfo.dst->ifindex)) == IP_NULL) goto done_out; switch (icmph->type) { case IPMIP4_ICMP_AGENT_ADVERTISEMENT: ipmipmn_icmp_input(data, proc, pbuf); break; } } else { /* Failure */ IPCOM_LOG0(ERR, "NO MAC"); } done_out: /* Free the packet buffer */ ipmip_pktbuf_release(&data->api.ipmip4.ipmip, proc, &pbuf->api.ipmip4.ipmip); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */