/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipha_if.c,v $ $Revision: 1.20.10.1 $ * $Source: /home/interpeak/CVSRoot/ipmipha/src/ipmipha_if.c,v $ * $Author: svc-cmnet $ * $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 #include "ipmipha.h" #include "ipmipha_h.h" #include "ipmipha_attr_h.h" #include "ipmipha_if.h" #include "ipmipha_agent.h" #include "ipmipha_node.h" #include "ipmipha_route.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipha_destroy_tunnel *=========================================================================== * Description: Destroy a particular tunnel. * Parameters: tunnel - The tunnel to destroy. * Returns: */ IP_STATIC void ipmipha_if_destroy_tunnel(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_tunnel_t *iff) { /* No tunnel, don't bother */ if (iff->iff.ipmip.ifindex == 0) return; /* Add the policy rule */ ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, data->route->inbound_table, IPMIPHA_ROUTE_PRID(0), iff->iff.ipmip.ifindex, IP_NULL, 0, IP_NULL, 0, 0, IP_FIB_RULE_FIND_SADDR); IPMIP_UNUSED_PARAMETER(data); IPMIP_UNUSED_PARAMETER(proc); } /* *=========================================================================== * ipmipha_if_create_tunnel *=========================================================================== * Description: Create a specific tunnel for the provided interface * Parameters: data - The FA configuration data structure * iff - The interface in question. * iname - Instance name * num - Configuration instance num * remote - The remote end * identity - The identity * tunnel_type - Kind of tunnel. * Returns: A newly allocated tunnel instance * */ IP_STATIC Ipmipha_iff_tunnel_t * ipmipha_if_create_tunnel(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_t *iff, Ip_u32 ifindex, Ip_u32 remote, Ip_u8 identity, Ip_u8 tunnel_type) { Ipmipha_iff_tunnel_t *tiff; char ifname[IP_IFNAMSIZ + 1]; /* Create the name */ ipcom_snprintf(ifname, sizeof(ifname), "%s%dha%x", ipmip_util_tunnel_to_bsdname(tunnel_type), tunnel_type, ifindex); tiff = (Ipmipha_iff_tunnel_t*)ipmip4_if_alloc_tunnel(&data->ipmip4, proc, sizeof(*tiff), ifname, iff->iff.ifaddr, data->ipmip4.pkt->s_udp_out.sin_port, remote, identity, tunnel_type, iff->reordering, (Ipmip_if_cleanup_t )ipmipha_if_destroy_tunnel); return tiff; } /* *=========================================================================== * ipmipha_if_delete *=========================================================================== * Description: Delete an interface * Parameters: iff - The interface to delete. * Returns: * */ IP_STATIC void ipmipha_if_delete(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_t *iff) { /* Free the final resources */ int i; ipmip4_auth_context_destroy(iff->security.spi_ctx); /* Free the SPI route tables */ ipmip4_auth_spi_table_destroy(iff->security.spi_fa); ipmip4_auth_spi_table_destroy(iff->security.spi_mn); ipmip4_auth_spi_hash_destroy(iff->security.spi_nai); if (iff->nai_ha) ipcom_free(iff->nai_ha); /**/ if (iff->security.spi_mn_lookup_order) ipcom_free(iff->security.spi_mn_lookup_order); /* Destroy the tunnels */ for (i = 0; i < IPMIP_TUNNELTYPE_MAX; i++) { if (iff->tunnels[i] != IP_NULL) ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->tunnels[i]->iff.ipmip); } ipmip_dhcp_rtab_destroy(iff->dhcp_rtab); /* Destroy the nodes */ ipmipha_node_context_destroy(data, proc, iff->nodes); /* Destroy the lock */ if (iff->if_lock) ipmip_timer_lock_destroy(&data->ipmip4.ipmip, proc, iff->if_lock); } /* *=========================================================================== * ipmipha_if_alloc *=========================================================================== * Description: Allocate a specified interface, and verify arch specific * data. * Parameters: data - The FA data structure. * ifname - The interface name. * Returns: The interface structure if successfull; IP_NULL otherwise. * */ IP_STATIC Ipmipha_iff_t * ipmipha_if_alloc(Ipmipha_data_t *data, Ipmip_proc_t *proc, const char *ifname) { /* Allocate an interface structure */ Ipmipha_iff_t *iff = IP_NULL; Ip_u32 ifindex; ifindex = ipcom_if_nametoindex(ifname); if (ifindex == 0) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Configuration failed, due to unknown interface '%s'", ifname)); return IP_NULL; } /* Allocate the structure */ iff = (Ipmipha_iff_t*)ipmip4_if_alloc(&data->ipmip4, proc, sizeof(*iff), ifname, ifindex, IPMIP_IF_TYPE_GENERIC, IPMIPHA_IFF_IDENTITY_HA, (Ipmip_if_cleanup_t )ipmipha_if_delete); /* Sanity */ if (iff == IP_NULL) return IP_NULL; /* Return the interface structure */ return iff; } /* *=========================================================================== * ipmipha_if_configure *=========================================================================== * Description: Post creation configuration * Parameters: data - The data * proc - Current process * iff - The interface we're configuring. * conf - The configuration context. * Returns: IP_TRUE if successful * */ IP_STATIC Ip_bool ipmipha_if_configure(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_t *iff, Ipmipha_conf_t *conf) { IPMIP_UNUSED_PARAMETER(conf); /* If we don't have the FA address, try resolve it */ if (iff->iff.ifaddr == 0) { /* Store extracted address */ iff->iff.ifaddr = ipmip4_if_get_primary_address(&data->ipmip4, proc, &iff->iff); /* Sanity */ if (iff->iff.ifaddr == IP_INADDR_NONE || iff->iff.ifaddr == IP_INADDR_ANY) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "auto-configuring: FAIL, %s returned for interface '%s'", ipmip_ntop_inet(proc, iff->iff.ifaddr), iff->iff.ipmip.ifname)); return IP_FALSE; } /**/ IPMIP4_EVENT_IF(INFO, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "auto-configuring: interface '%s' configured to use %s", iff->iff.ipmip.ifname, ipmip_ntop_inet(proc, iff->iff.ifaddr))); } /* Get MAC address. */ if (ipmip_if_resolve_lla(&data->ipmip4.ipmip, proc, &iff->iff.ipmip) == IP_FALSE) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Unable to retrieve link-layer address for interface '%s'", iff->iff.ipmip.ifname)); return IP_FALSE; } /* Need to install the routing policy forcing traffic to the fwd table */ { int i; /*!!CALLED ONCE PER INTERFACE?? ADV_FD ONE PER INTERFACE?? Listen to solicitations sent to 224.0.0.1 */ if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLHOSTS_GROUP), iff->iff.ipmip.ifindex)) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Unable to join all hosts group on interface '%s'", iff->iff.ipmip.ifname)); return IP_FALSE; } /* Listen to solicitations sent to 224.0.0.2 */ if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLRTRS_GROUP), iff->iff.ipmip.ifindex)) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Unable to join all routers group on interface '%s'", iff->iff.ipmip.ifname)); return IP_FALSE; } /* Listen to solicitations sent to the Mobile-Agents multicast group 224.0.0.11 */ if (!ipmip4_pkt_icmp_join(&data->ipmip4, proc, ip_htonl(IP_INADDR_ALLMA_GROUP), iff->iff.ipmip.ifindex)) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Unable to join all mobile agents group on interface '%s'", iff->iff.ipmip.ifname)); return IP_FALSE; } if (iff->adv_address != ip_htonl(IP_INADDR_ALLHOSTS_GROUP) && iff->adv_address != ip_htonl(IP_INADDR_ALLRTRS_GROUP) && iff->adv_address != ip_htonl(IP_INADDR_ALLMA_GROUP) && IP_IN_CLASSD(iff->adv_address)) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Bad advertisement group %s on interface '%s'", ipmip_ntop_inet(proc, iff->adv_address), iff->iff.ipmip.ifname)); return IP_FALSE; } /* IPIP tunnel */ for (i = 0; i < IPMIP_TUNNELTYPE_MAX; i++) { if (iff->tunnel.enabled[i]) { iff->tunnels[i] = ipmipha_if_create_tunnel(data, proc, iff, iff->iff.ipmip.ifindex, IP_INADDR_ANY, IPMIPHA_IFF_IDENTITY_HA_TUNNEL, i); /**/ if (iff->tunnels[i] == IP_NULL) iff->tunnel.enabled[i] = IP_FALSE; else { /* Add the policy rule */ ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, data->route->inbound_table, IPMIPHA_ROUTE_PRID(0), iff->tunnels[i]->iff.ipmip.ifindex, IP_NULL, 0, IP_NULL, 0, 0, IP_FIB_RULE_FIND_SADDR); } } } } return IP_TRUE; } /* *=========================================================================== * ipmipha_if_output_timeout *=========================================================================== * Description: Periodically send RtAdv. * Parameters: iff - The interface we're sending on. * Returns: IP_TRUE * */ IP_STATIC Ip_bool ipmipha_if_advert_output_timeout(int event, Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_iff_t *iff, void *extra) { IPMIP_UNUSED_PARAMETER(extra); if (event == IPMIP_TIMER_EVENT_RUN) { /* Output it */ if (IP_BIT_ISFALSE(data->shutdown, IPMIPHA_SHUTDOWN_ADV)) ipmipha_agent_advert_output(data, proc, iff, IP_NULL, IP_NULL); } else { /* Do nothing on cancellation */ } return IPMIP_TIMER_RET_REINSERT; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipha_if_create *=========================================================================== * Description: Create an interface for a specified configuration. * Parameters: data - The FA entity. * proc - Current process. * conf - The current configuration. * ifname - The name of the interface. * Returns: IP_TRUE if successful. * */ IP_GLOBAL Ip_bool ipmipha_if_create(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_conf_t *conf, const char *ifname) { Ipmipha_iff_t *iff; unsigned si; int i; /* Try create the interface in question */ if ((iff = ipmipha_if_alloc(data,proc,ifname)) == IP_NULL) return IP_FALSE; iff->nodes = ipmipha_node_context_alloc(data, proc); if (iff->nodes == IP_NULL) goto fail; iff->dhcp_rtab = ipmip_dhcp_rtab_create(&data->ipmip4.ipmip, proc, IP_NULL); /* Store it */ ipcom_list_insert_first(&conf->if_head, &iff->iff.ipmip.next); /* Initialize the lock */ iff->if_lock = ipmip_timer_lock_alloc(&data->ipmip4.ipmip, proc, IP_NULL, IP_NULL); /* Create the security context */ iff->security.spi_ctx = ipmip4_auth_context_create(); iff->security.spi_fa = ipmip4_auth_spi_table_create(iff->security.spi_ctx); iff->security.spi_mn = ipmip4_auth_spi_table_create(iff->security.spi_ctx); iff->security.spi_nai = ipmip4_auth_spi_hash_create(iff->security.spi_ctx); /* Do the SPI tables */ iff->security.spi_fa_lookup_required = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.fa.sa.lookup.required"), "ipmipha.if.%s.fa.sa.lookup.required", iff->iff.ipmip.ifname); iff->security.spi_mn_lookup_required = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.mn.sa.lookup.required"), "ipmipha.if.%s.mn.sa.lookup.required", iff->iff.ipmip.ifname); /* Read SPI's */ ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi, iff->security.spi_ctx, "ipmipha.if.%s.spi.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi, iff->security.spi_ctx, "ipmipha.spi.*"); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_fa, "ipmipha.if.%s.fa.sa.address.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_fa, "ipmipha.fa.sa.address.*"); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_mn, "ipmipha.if.%s.mn.sa.address.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_mn, "ipmipha.mn.sa.address.*"); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spihash, iff->security.spi_nai, "ipmipha.if.%s.mn.sa.nai.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spihash, iff->security.spi_nai, "ipmipha.mn.sa.nai.*"); /* Initialize ADV timeout */ IPMIP_TIMER_INIT(&iff->adv_timer); /* Get foreign agent addresses. Reachable by foreign subnets. */ ipmip_sysvar_inet(0, &iff->iff.ifaddr, IP_NULL, "ipmipha.if.%s.homeagent", iff->iff.ipmip.ifname); /* Backward compatibility */ iff->lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(ipmip_sysvar_ulong(0, "ipmipha.lifetime"), "ipmipha.reg_lifetime"), "ipmipha.if.%s.lifetime", iff->iff.ipmip.ifname); if (iff->lifetime == 0) iff->lifetime = 0xffff; iff->replay_diff = ipmip_sysvar_long(ipmip_sysvar_long(ipmip_sysvar_long(0, "ipmipha.timestamp_replay_protection_max_diff"), "ipmipha.timestampreplayprotectionmaxdiff"), "ipmipha.if.%s.timestamp_replay_protection_max_diff", iff->iff.ipmip.ifname); if ((iff->nai_ha = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_ha("ipmipha.if.%s.nai.ha", iff->iff.ipmip.ifname)) == IP_NULL) iff->nai_ha = (Ipmip4_msgext_uhdr_t *)ipmip4_sysext_nai_ha("ipmipha.nai.ha"); iff->mn_nai_require = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.mn.nai.required"), "ipmipha.if.%s.mn.nai.required", iff->iff.ipmip.ifname); /* Resolve the home netmask */ if (!ipmip_sysvar_inet(ip_htonl(0xffffff00), &iff->home_netmask, IP_NULL, "ipmipha.if.%s.homenetmask", iff->iff.ipmip.ifname)) ipmip_sysvar_inet(ip_htonl(0xffffff00), &iff->home_netmask, IP_NULL, "ipmipha.homenetmask"); if ((iff->security.spi_mn_lookup_order = ipmip_sysvar_array(ipmipha_attr_lookup, "ipmipha.if.%s.mn.sa.lookup.order", iff->iff.ipmip.ifname)) == IP_NULL) iff->security.spi_mn_lookup_order = ipmip_sysvar_array(ipmipha_attr_lookup, "ipmipha.mn.sa.lookup.order"); if (iff->security.spi_mn_lookup_order == IP_NULL) { iff->security.spi_mn_lookup_order = ipcom_calloc(3, sizeof(int)); if (iff->security.spi_mn_lookup_order == IP_NULL) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Failed to allocate memory required for lookup order structure", iff->iff.ipmip.ifname)); goto fail; } /**/ iff->security.spi_mn_lookup_order[0] = IPMIPHA_SPI_MN_HOA; iff->security.spi_mn_lookup_order[1] = IPMIPHA_SPI_MN_NAI; iff->security.spi_mn_lookup_order[2] = IPMIPHA_SPI_MN_NONE; } /* Get ADV lifetime */ iff->adv_lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(50, "ipmipha.adv_lifetime"), "ipmipha.if.%s.adv_lifetime", iff->iff.ipmip.ifname); /* Get ADV interval */ iff->adv_interval = ipmip_sysvar_long(ipmip_sysvar_long(10, "ipmipha.adv_interval"), "ipmipha.if.%s.adv_interval", iff->iff.ipmip.ifname); /* Get ADV address */ if (!ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipha.if.%s.adv_address", iff->iff.ipmip.ifname)) ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipha.adv_address"); if (iff->adv_address == 0) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Bad advertisement group %s on interface '%s'", ipmip_ntop_inet(proc, iff->adv_address), iff->iff.ipmip.ifname)); goto fail; } /* NAT-T configuration */ iff->nat_t = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.nat_t.enabled"), "ipmipha.if.%s.nat_t.enabled", iff->iff.ipmip.ifname); iff->nat_t_keepalive = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(0, "ipmipha.nat_t.keepalive"), "ipmipha.if.%s.nat_t.keepalive", iff->iff.ipmip.ifname); /* Do we require foreign agent authentication */ iff->fa_auth = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.fa_auth"), "ipmipha.if.%s.fa_auth", iff->iff.ipmip.ifname); /* Do we require foreign agent authentication */ iff->reordering = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipha.tunnel.reordering"), "ipmipha.if.%s.tunnel.reordering", iff->iff.ipmip.ifname); /* Reverse tunneling state? */ iff->tunnel.reverse = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipha.tunnel.reverse"), "ipmipha.if.%s.tunnel.reverse", iff->iff.ipmip.ifname); /**/ iff->tunnel.enabled[IPMIP_TUNNELTYPE_NONE] = IP_TRUE; /* IPIP allowed */ iff->tunnel.enabled[IPMIP_TUNNELTYPE_IPIP] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.tunnel.ipip"), "ipmipha.if.%s.tunnel.ipip", iff->iff.ipmip.ifname); /* GRE allowed? */ iff->tunnel.enabled[IPMIP_TUNNELTYPE_GRE] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.tunnel.gre"), "ipmipha.if.%s.tunnel.gre", iff->iff.ipmip.ifname); /* MINENC allowed? */ iff->tunnel.enabled[IPMIP_TUNNELTYPE_MINENC] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.tunnel.minenc"), "ipmipha.if.%s.tunnel.minenc", iff->iff.ipmip.ifname); /* Simultaneous bindings */ iff->simbind_enabled = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.simbind.enable"), "ipmipha.if.%s.simbind.enable", iff->iff.ipmip.ifname); iff->simbind_max = ipmip_sysvar_ulong(ipmip_sysvar_ulong(3, "ipmipha.simbind.max"), "ipmipha.if.%s.simbind.max", iff->iff.ipmip.ifname); iff->revocation = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipha.revocation.enabled"), "ipmipha.if.%s.revocation.enabled", iff->iff.ipmip.ifname); iff->revocation_inform = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipha.revocation.inform"), "ipmipha.if.%s.revocation.inform", iff->iff.ipmip.ifname); if (!ipmipha_if_configure(data, proc, iff, conf)) goto fail; iff->ha_subbrd = iff->iff.ifaddr | ~iff->home_netmask; iff->ha_netbrd = iff->iff.ifaddr | ~IP_NETMASK(iff->iff.ifaddr); /* Do the external parsing */ /* Do the external parsing */ for (i = IPMIPHA_FUNCTION_MAX - 1; i >= 0; i--) { for (si = 0; si < data->extensions[i].num; si++) { if (data->extensions[i].functions[si]->config_ifp != IP_NULL) { if (data->extensions[i].functions[si]->ifp_data_size) { iff->extdata[i][si] = ipcom_calloc(1, data->extensions[i].functions[si]->ifp_data_size); (*data->extensions[i].functions[si]->config_ifp) (data, proc, IPMIP_CALLBACK_CONFIG_READ, iff, conf->extdata[i][si], iff->extdata[i][si], IP_NULL); } } } } return IP_TRUE; fail: ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->iff.ipmip); return IP_FALSE; } /* *=========================================================================== * ipmipha_if_start *=========================================================================== * Description: Start interfaces for a specified configuration. * Parameters: data - The FA entity. * proc - Current process. * Returns: * */ IP_GLOBAL void ipmipha_if_start(Ipmipha_data_t *data, Ipmip_proc_t *proc) { Ipmipha_iff_t *iff; if (data->conf == IP_NULL) return; /* free interface list */ for (iff = IPCOM_LIST_FIRST(&data->conf->if_head); iff != IP_NULL; iff = IPCOM_LIST_NEXT(&iff->iff.ipmip.next)) { /* Is it activated? */ if (iff->adv_interval > 0) { ipmip_timer_request(&data->ipmip4.ipmip, proc, &iff->adv_timer, iff->if_lock, (Ipmip_timer_func_t)ipmipha_if_advert_output_timeout, iff, IP_NULL, iff->adv_interval * 1000); } } } /* *=========================================================================== * ipmipfa_if_start *=========================================================================== * Description: Start an interface for a specified configuration. * Parameters: data - The FA entity. * proc - Current process. * Returns: * */ IP_GLOBAL void ipmipha_if_stop(Ipmipha_data_t *data, Ipmip_proc_t *proc, Ipmipha_conf_t *conf) { Ipmipha_iff_t *iff; /* Send instant RtAdv on all active interfaces */ while (IP_NULL != (iff = IPCOM_LIST_FIRST(&conf->if_head))) { int i; unsigned si; for (i = IPMIPHA_FUNCTION_MAX - 1; i >= 0; i--) { for (si = 0; si < data->extensions[i].num; si++) { if (data->extensions[i].functions[si]->config_ifp != IP_NULL) { if (iff->extdata[i][si]) { (*data->extensions[i].functions[si]->config_ifp) (data, proc, IPMIP_CALLBACK_CONFIG_FREE, iff, conf->extdata[i][si], iff->extdata[i][si], IP_NULL); ipcom_free(iff->extdata[i][si]); iff->extdata[i][si] = IP_NULL; } } } } ipmip_if_free(&data->ipmip4.ipmip, proc, &iff->iff.ipmip); } } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */