/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipha_agent.c,v $ $Revision: 1.11 $ * $Source: /home/interpeak/CVSRoot/ipmipha/src/ipmipha_agent.c,v $ * $Author: jhorteli $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmipha_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 "ipmipha.h" #include "ipmipha_h.h" #include "ipmipha_attr_h.h" #include "ipmipha_if.h" #include "ipmipha_agent.h" #include "ipmipha_pktbuf.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipha_agent_advert_build *=========================================================================== * Description: Create an advertisement. * Parameters: data - Context * proc - Process * adv - The buffer to create the advertisement in. * iff - The interface for which we create the buffer. * lla_ext - Append the interfaces LLA extension * Returns: IP_TRUE on success. * */ IP_STATIC Ip_bool ipmipha_agent_advert_build(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmip_buffer_t *adv, Ipmipha_iff_t *iff) { Ipmip4_icmp_advert_t advpkt; Ipmip4_icmp_advert_t *advpktp; Ipmip4_icmp_ext_advert_t adv_ext; Ip_u16 adv_seq; ipcom_memset(&advpkt, 0, sizeof(advpkt)); ipcom_memset(&adv_ext, 0, sizeof(adv_ext)); /* ICMP advertisement header */ advpkt.icmp_type = IPMIP4_ICMP_AGENT_ADVERTISEMENT; advpkt.icmp_code = data->ipnet_is_router ? IPMIP4_ICMP_CODE_GENERIC_ROUTER : IPMIP4_ICMP_CODE_AGENT_ONLY; advpkt.icmp_checksum = 0; advpkt.adv_num_addrs = 0; advpkt.adv_addr_entry_size = 2; advpkt.adv_lifetime = ip_htons(iff->adv_lifetime); ipmip_buffer_append(adv, &advpkt, sizeof(advpkt)); /* Store */ adv_seq = iff->adv_seq; /* Add mobility agent advertisement extension */ adv_ext.type = IPMIP4_ICMP_EXT_TYPE_MOBILITY_AGENT_ADV; adv_ext.length = 6; adv_ext.seq = ip_htons(adv_seq); adv_ext.reg_lifetime = ip_htons(iff->lifetime); adv_ext.flags = ip_ntohs(IPMIP4_ICMP_ADVEXT_FLAG_HOME_AGENT); ipmip_buffer_append(adv, &adv_ext, sizeof(adv_ext) - sizeof(adv_ext.coa)); if (iff->nai_ha != IP_NULL) ipmip4_msgext_buffer_append_shdr(adv, iff->nai_ha); if (++iff->adv_seq == 0) /* Roll-over prevention, so it does not look like we have rebooted */ iff->adv_seq = 256; advpktp = IPMIP_BUFFER_PTR(adv); advpktp->icmp_checksum = ipcom_in_checksum(IPMIP_BUFFER_DATA(adv), IPMIP_BUFFER_SIZE(adv)); IPMIP4_EVENT_IF(DEBUG2, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Sending Router Advertisement on %s with sequence #%u", iff->iff.ipmip.ifname, adv_seq)); /* Return advlen */ return IP_TRUE; } /* *=========================================================================== * ipmipha_agent_solicitation_input *=========================================================================== * Description: Process received ICMP Agent solicitations. * Parameters: pbuf - The packet buffer * Returns: * */ IP_STATIC Ip_bool ipmipha_agent_solicitation_input(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_pktbuf_t *pbuf) { Ip_u8 *ext_start; int ext_len; int i; Ipmip4_icmp_solicit_t *solpkt; int sol_len; /* Solicitation packet */ solpkt = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet); sol_len = sizeof(Ipmip4_icmp_solicit_t); if (IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) < (unsigned)sol_len) return IP_FALSE; if (pbuf->ipmip4.ipmip.srcinfo.ttl != 1) { IPMIP4_EVENT_IF(WARNING, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Router Solicitation input on %s from %s failed since TTL != 1", pbuf->iff.pub->ipmip.ifname, ipmip_ntop_inet(proc, pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr))); return IP_FALSE; } /* Extension part */ ext_start = ipmip_buffer_offset(&pbuf->ipmip4.ipmip.packet, sol_len); ext_len = IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) - sol_len; i = ipmip4_msgext_icmp_parse(proc, pbuf->iff.pub->ipmip.ifname, pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr, &pbuf->ipmip4.ext.icmp, ext_start, ext_len); if (i != IPMIP4_REG_EXT_SUCCESS) return IP_FALSE; IPMIP4_EVENT_IF(DEBUG2, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Router Solicitation received on %s from %s/%s", pbuf->iff.pub->ipmip.ifname, ipmip_ntop_inet(proc, pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr), ipmip_ntop_lladdr(proc, pbuf->ipmip4.ipmip.srcinfo.lladdr))); /* Write a directed output */ ipmipha_agent_advert_output(data, proc, pbuf->iff.priv, (Ip_u32 *)&pbuf->ipmip4.ipmip.srcinfo.src->sin.sin_addr.s_addr, pbuf->ipmip4.ipmip.srcinfo.lladdr); return IP_FALSE; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipha_agent_advert_output *=========================================================================== * Description: Write an ordinary multicast/unicast advertisement * Parameters: data - Context * proc - Process * iff - The interface to send the advertisment from. * dst - If specified, unicast dst address * lla - If specified, unicast LLA address * Returns: * */ IP_GLOBAL void ipmipha_agent_advert_output(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_t *iff, Ip_u32 *dst, Ipmip_lladdr_t *lladdr) { Ipmip_buffer_t adv; ipmip_buffer_init(&adv); /* Create the advertisement */ if (ipmipha_agent_advert_build(data, proc, &adv, iff)) { /* If dst is zero, specify it as the advertisement address */ if (dst == IP_NULL) dst = &iff->adv_address; /* Write the request */ if (ipmip4_pkt_icmp_write(&data->ipmip4, proc, &adv, iff->iff.ifaddr, *dst, &iff->iff, lladdr) != IP_TRUE) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Failed to send %s Router Advertisement on %s", (dst == &iff->adv_address)? "unicast" : "multicast", iff->iff.ipmip.ifname)); } ipmip_buffer_release(&adv); } } /* *=========================================================================== * ipmipha_adv_recv *=========================================================================== * Description: Handles incoming advertisements or solicitations * Parameters: data - Context * proc - Current process. * pbuf - Packet buffer * Returns: * */ IP_GLOBAL void ipmipha_adv_recv(struct Ipmipha_data *data, struct Ipmip_proc *proc, Ipmipha_pktbuf_t *pbuf) { if (data->conf == IP_NULL) return; if (pbuf->ipmip4.ipmip.srcinfo.lladdr != IP_NULL) { Ipcom_icmp_header *icmph = IPMIP_BUFFER_PTR(&pbuf->ipmip4.ipmip.packet); /* Truncated packet? */ if (IPMIP_BUFFER_SIZE(&pbuf->ipmip4.ipmip.packet) < IPCOM_ICMP_HEADER_LENGTH) goto done_out; if (pbuf->ipmip4.ipmip.srcinfo.dst->dst.sin.sin_addr.s_addr == ip_htonl(IP_INADDR_ALLHOSTS_GROUP) || pbuf->ipmip4.ipmip.srcinfo.dst->dst.sin.sin_addr.s_addr == ip_htonl(IP_INADDR_ALLRTRS_GROUP) || pbuf->ipmip4.ipmip.srcinfo.dst->dst.sin.sin_addr.s_addr == ip_htonl(IP_INADDR_ALLMA_GROUP) || pbuf->ipmip4.ipmip.srcinfo.dst->dst.sin.sin_addr.s_addr == 0xffffffff) { /* Must find the interface */ if ((pbuf->iff.pub = (Ipmip4_if_t *)ipmip_if_findbyindex(&data->conf->if_head, pbuf->ipmip4.ipmip.srcinfo.dst->ifindex)) == IP_NULL) goto done_out; } else if ((pbuf->iff.pub = ipmip4_if_findbyaddr(&data->conf->if_head, pbuf->ipmip4.ipmip.srcinfo.dst->dst.sin.sin_addr.s_addr)) == IP_NULL) goto done_out; switch (icmph->type) { case IPMIP4_ICMP_ROUTER_SOLICITATION: if (IP_BIT_ISFALSE(data->shutdown, IPMIPHA_SHUTDOWN_ADV)) { if (ipmipha_agent_solicitation_input(data, proc, pbuf)) return; } } } done_out: /* Free the packet buffer */ ipmip_pktbuf_release(&data->ipmip4.ipmip, proc, &pbuf->ipmip4.ipmip); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */