/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmipfa_if.c,v $ $Revision: 1.29.10.1 $ * $Source: /home/interpeak/CVSRoot/ipmipfa/src/ipmipfa_if.c,v $ * $Author: svc-cmnet $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmipfa_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 #if 0 #include #include #endif #include #include #include #include #include #include #include #include #include "ipmipfa.h" #include "ipmipfa_h.h" #include "ipmipfa_if.h" #include "ipmipfa_agent.h" #include "ipmipfa_reg.h" #include "ipmipfa_node.h" #include "ipmipfa_route.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ typedef struct Ipmipfa_iff_tunnel { Ipmip4_if_t iff; Ipmipfa_iff_t *master; #if 0 struct Ipnet_policy_routing_rule blk_rt_rule; /* Tunneled IF to Tunnel rule table */ struct Ipnet_policy_routing_rule lkl_rt_rule; /* Local IF to Tunnel rule table */ #endif } Ipmipfa_iff_tunnel_t; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipfa_if_delete *=========================================================================== * Description: Delete an interface * Parameters: iff - The interface to delete. * Returns: * */ IP_STATIC void ipmipfa_if_delete(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff) { /* Free the final resources */ int i; ipmipfa_llh_config_exit(data, proc, iff); /* free spi list */ ipmip4_auth_context_destroy(iff->security.spi_ctx); /* Free the SPI route tables */ ipmip4_auth_spi_table_destroy(iff->security.spi_ha); ipmip4_auth_spi_table_destroy(iff->security.spi_fa); ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, iff->tnl_table, IPMIPFA_ROUTE_PRID(0), iff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, IP_FIB_RULE_FIND_SADDR); /* 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]->ipmip); } /* Destroy the node context */ ipmipfa_node_context_destroy(data, proc, iff->node); /* Destroy black hole route table */ ipmip_util_route_table_free(&data->ipmip4.ipmip, proc, iff->fwd_table); ipmip_util_route_table_free(&data->ipmip4.ipmip, proc, iff->tnl_table); if (iff->link_layer) ipcom_free(iff->link_layer); /* Destroy the lock */ ipmip_timer_lock_destroy(&data->ipmip4.ipmip, proc, iff->if_lock); } /* *=========================================================================== * ipmipfa_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 Ipmipfa_iff_t * ipmipfa_if_alloc(Ipmipfa_data_t *data, Ipmip_proc_t *proc, const char *ifname) { /* Allocate an interface structure */ Ipmipfa_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, "Unknown interface '%s'", ifname)); return IP_NULL; } /* Allocate the structure */ iff = (Ipmipfa_iff_t*)ipmip4_if_alloc(&data->ipmip4, proc, sizeof(*iff), ifname, ifindex, IPMIP_IF_TYPE_GENERIC, IPMIPFA_IFF_IDENTITY_FA, (Ipmip_if_cleanup_t )ipmipfa_if_delete); /* Sanity */ if (iff == IP_NULL) return IP_NULL; /* Return the interface structure */ return iff; } /* *=========================================================================== * ipmipfa_if_challenge_next *=========================================================================== * Description: Generate the next challenge. * Parameters: iff - The interface we're working on. * Returns: * */ IP_STATIC void ipmipfa_if_challenge_next(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff) { int i; /* Advance */ iff->current_challenge++; /* The index */ i = iff->current_challenge % IPMIPFA_CONF_CHALLENGE_WINDOW; /* Generate it */ ipmipfa_if_challenge_generate(data, proc, iff, iff->challenge_window[i]); } /* *=========================================================================== * ipmipfa_if_output_timeout *=========================================================================== * Description: Periodically send RtAdv. * Parameters: iff - The interface we're sending on. * Returns: IP_TRUE * */ IP_STATIC Ip_bool ipmipfa_if_advert_output_timeout(int event, Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff, void *extra) { IPMIP_UNUSED_PARAMETER(extra); if (event == IPMIP_TIMER_EVENT_RUN) { if (IP_BIT_ISFALSE(data->shutdown, IPMIPFA_SHUTDOWN_MUTE)) { /* Generate next challenge */ ipmipfa_if_challenge_next(data, proc, iff); /* Output it */ ipmipfa_agent_advert_output(data, proc, iff, IP_NULL, IP_NULL, IP_NULL, IP_FALSE); } } else { /* Do nothing on cancellation */ } return IPMIP_TIMER_RET_REINSERT; } /* *=========================================================================== * ipmipfa_destroy_tunnel *=========================================================================== * Description: Destroy a particular tunnel. * Parameters: tunnel - The tunnel to destroy. * Returns: */ IP_STATIC void ipmipfa_if_destroy_tunnel(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_tunnel_t *iff) { /* No tunnel, don't bother */ if (iff->iff.ipmip.ifindex == 0) return; ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, data->route->blk_table, IPMIPFA_ROUTE_PRID(-2), iff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, 0); ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, iff->master->fwd_table, IPMIPFA_ROUTE_PRID(-1), iff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, 0); } /* *=========================================================================== * ipmipfa_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 Ipmip4_if_t * ipmipfa_if_create_tunnel(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff, Ip_u32 ifindex, Ip_u32 remote, Ip_u8 identity, Ip_u8 tunnel_type) { Ipmipfa_iff_tunnel_t *tiff; char ifname[IP_IFNAMSIZ + 1]; /* Create the name */ ipcom_snprintf(ifname, sizeof(ifname), "%s%dfa%x", ipmip_util_tunnel_to_bsdname(tunnel_type), tunnel_type, ifindex); tiff = (Ipmipfa_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 )ipmipfa_if_destroy_tunnel); if (tiff == IP_NULL) return IP_NULL; /* Store master interface */ tiff->master = iff; ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, data->route->blk_table, IPMIPFA_ROUTE_PRID(-2), tiff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, 0); ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, iff->fwd_table, IPMIPFA_ROUTE_PRID(-1), tiff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, 0); IPMIP4_EVENT_IF(DEBUG2, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Created tunnel interface '%s'", tiff->iff.ipmip.ifname)); return &tiff->iff; } /* *=========================================================================== * ipmipfa_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 ipmipfa_if_configure(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff, Ipmipfa_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 CoA %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] = ipmipfa_if_create_tunnel(data, proc, iff, iff->iff.ipmip.ifindex, IP_INADDR_ANY, IPMIPFA_IFF_IDENTITY_FA_TUNNEL, i); } } return IP_TRUE; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipfa_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 ipmipfa_if_create(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_conf_t *conf, const char *ifname) { Ipmipfa_iff_t *iff; int i; unsigned si; char *dptr; /* Try create the interface in question */ if ((iff = ipmipfa_if_alloc(data,proc,ifname)) == IP_NULL) return IP_FALSE; /**/ if ((iff->node = ipmipfa_node_context_alloc(data, proc)) == IP_NULL) goto fail; iff->tnl_table = ipmip_util_route_table_alloc(&data->ipmip4.ipmip, proc); iff->fwd_table = ipmip_util_route_table_alloc(&data->ipmip4.ipmip, proc); ipmip_netlink_inX_rule(&data->ipmip4.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, iff->tnl_table, IPMIPFA_ROUTE_PRID(0), iff->iff.ipmip.ifindex, IP_NULL, 0, 0, 0, 0, IP_FIB_RULE_FIND_SADDR); iff->conf = conf; /* Initialize the lock */ iff->if_lock = ipmip_timer_lock_alloc(&data->ipmip4.ipmip, proc, IP_NULL, IP_NULL); /* Create the security setup */ iff->security.spi_ctx = ipmip4_auth_context_create(); iff->security.spi_ha = ipmip4_auth_spi_table_create(iff->security.spi_ctx); iff->security.spi_fa = ipmip4_auth_spi_table_create(iff->security.spi_ctx); /* Initialize ADV timeout */ IPMIP_TIMER_INIT(&iff->adv_timer); /**/ ipcom_list_init(&iff->fa_head); /* Store it */ ipcom_list_insert_first(&conf->if_head, &iff->iff.ipmip.next); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi, iff->security.spi_ctx, "ipmipfa.if.%s.spi.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spi, iff->security.spi_ctx, "ipmipfa.spi.*"); /* Read the SPI lookup definitions */ ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_ha, "ipmipfa.if.%s.ha.sa.address.*", iff->iff.ipmip.ifname); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_ha, "ipmipfa.ha.sa.address.*"); ipmip_sysvar_foreach(proc, (Ipmip_sysvar_foreach_t) ipmip4_sysext_foreach_spiroute, iff->security.spi_fa, "ipmipfa.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, "ipmipfa.fa.sa.address.*"); iff->security.spi_ha_lookup_required = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.ha.sa.lookup.required"), "ipmipfa.if.%s.ha.sa.lookup.required", iff->iff.ipmip.ifname); /* Get foreign agent addresses. Reachable by foreign subnets. */ ipmip_sysvar_inet(0, &iff->iff.ifaddr, IP_NULL, "ipmipfa.if.%s.foreignagent", iff->iff.ipmip.ifname); /* Get ADV lifetime */ iff->mn_auth = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.mn_auth"), "ipmipfa.if.%s.mn_auth", iff->iff.ipmip.ifname); /* Get ADV lifetime */ iff->adv_lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(300, "ipmipfa.adv_lifetime"), "ipmipfa.if.%s.adv_lifetime", iff->iff.ipmip.ifname); /* Get ADV interval */ iff->adv_interval = ipmip_sysvar_long(10, "ipmipfa.if.%s.adv_interval", iff->iff.ipmip.ifname); iff->lifetime = (Ip_u16)ipmip_sysvar_ulong(ipmip_sysvar_ulong(ipmip_sysvar_ulong(60, "ipmipfa.lifetime"), "ipmipfa.reg_lifetime"), "ipmipfa.if.%s.lifetime", iff->iff.ipmip.ifname); if (iff->lifetime == 0) iff->lifetime = 0xffff; /* infinite */ /* Get ADV address */ if (!ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipfa.if.%s.adv_address", iff->iff.ipmip.ifname)) ipmip_sysvar_inet(ip_htonl(IP_INADDR_ALLMA_GROUP), &iff->adv_address, IP_NULL, "ipmipfa.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; } /* FA Error Extension (RFC4636) */ iff->ext.fa_error = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.ext.fa_error"), "ipmipfa.if.%s.ext.fa_error", iff->iff.ipmip.ifname);; /* DHAA (RFC4433) */ iff->ext.dhaa = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.ext.dhaa"), "ipmipfa.if.%s.ext.dhaa", iff->iff.ipmip.ifname); if (!ipmip_sysvar_inet(0, &iff->ext.dhaa_address, IP_NULL, "ipmipfa.if.%s.ext.dhaa.address", iff->iff.ipmip.ifname)) ipmip_sysvar_inet(0, &iff->ext.dhaa_address, IP_NULL, "ipmipfa.ext.dhaa.address"); /* Challenge (RFC3012) */ iff->ext.challenge = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.challenge"), "ipmipfa.if.%s.challenge", iff->iff.ipmip.ifname); /* */ iff->ext.revocation = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.revocation.enabled"), "ipmipfa.if.%s.revocation.enabled", iff->iff.ipmip.ifname); iff->ext.revocation_inform = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipfa.revocation.inform"), "ipmipfa.if.%s.revocation.inform", iff->iff.ipmip.ifname); /* Reverse tunneling state? */ iff->tunnel.reverse = ipmip_sysvar_mode(ipmip_sysvar_mode(IPMIP_SYSVAR_MODE_OPTIONAL, "ipmipfa.tunnel.reverse"), "ipmipfa.if.%s.tunnel.reverse", iff->iff.ipmip.ifname); /**/ iff->tunnel.enabled[IPMIP_TUNNELTYPE_NONE] = IP_TRUE; /* Get tunnel reordering */ iff->reordering = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.tunnel.reordering"), "ipmipfa.if.%s.tunnel.reordering", iff->iff.ipmip.ifname); /**/ iff->tunnel.enabled[IPMIP_TUNNELTYPE_IPIP] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.ipip"), "ipmipfa.if.%s.tunnel.ipip", iff->iff.ipmip.ifname); /* GRE allowed? */ iff->tunnel.enabled[IPMIP_TUNNELTYPE_GRE] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.gre"), "ipmipfa.if.%s.tunnel.gre", iff->iff.ipmip.ifname); /* MINENC allowed? */ iff->tunnel.enabled[IPMIP_TUNNELTYPE_MINENC] = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.tunnel.minenc"), "ipmipfa.if.%s.tunnel.minenc", iff->iff.ipmip.ifname); /* NAT-T enabled? */ iff->nat_t = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_TRUE, "ipmipfa.nat_t.enabled"), "ipmipfa.if.%s.nat_t.enabled", iff->iff.ipmip.ifname); /* NAT-T keepalive? */ iff->nat_t_keepalive = (Ip_u8)ipmip_sysvar_ulong(ipmip_sysvar_ulong(120, "ipmipfa.nat_t.keepalive"), "ipmipfa.if.%s.nat_t.keepalive", iff->iff.ipmip.ifname); /* NAT-T forced if enabled? */ iff->nat_t_force = ipmip_sysvar_bool(ipmip_sysvar_bool(IP_FALSE, "ipmipfa.nat_t.forced"), "ipmipfa.if.%s.nat_t.forced", iff->iff.ipmip.ifname); /* Get tunnel type */ i = ipmip4_sysext_tunnel_type(ipmip4_sysext_tunnel_type(IPMIP_TUNNELTYPE_NONE, "ipmipfa.nat_t.tunnel_type"), "ipmipfa.if.%s.nat_t.tunnel_type", iff->iff.ipmip.ifname); if (i == -1) { IPMIP4_EVENT_IF(ERR, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "invalid 'nat_t.tunnel_type' configuration in UDP encap for interface '%s'", iff->iff.ipmip.ifname)); goto fail; } iff->nat_t_tunnel = (Ip_u8)i; /* Configure the interface */ if (ipmipfa_if_configure(data, proc, iff, conf) == IP_FALSE) goto fail; /* Generate a window full of challenges */ for (i = 0; i < IPMIPFA_CONF_CHALLENGE_WINDOW; i++) ipmipfa_if_challenge_next(data, proc, iff); if ((dptr = ipmip_sysvar("ipmipfa.if.%s.link.layer", iff->iff.ipmip.ifname)) == IP_NULL) dptr = ipmip_sysvar("ipmipfa.link.layer"); /* */ if (dptr != IP_NULL) { iff->link_layer = ipmip_lladdr_parse(proc, iff->iff.ipmip.lladdr->type, iff->iff.ipmip.lladdr->subtype, dptr); ipcom_free(dptr); if (iff->link_layer) { ipmip_if_clear_flags(&data->ipmip4.ipmip, proc, &iff->iff.ipmip, IP_IFF_UP); /* Assign LLADDR */ if (ipmip_netlink_link(&data->ipmip4.ipmip, proc, IP_RTM_SETLINK, iff->iff.ipmip.ifindex, 0, 0, IPMIP_LLADDR_DATA(iff->link_layer), IPMIP_LLADDR_LEN_LLA(iff->link_layer), 0) != 0) { /* Do something */ IPMIP4_EVENT_IF(WARNING, proc, ipmip_log_event_add(&data->ipmip4.ipmip, proc, "Foreign Agent interface %s unable to assign Link-Layer address", iff->iff.ipmip.ifname)); } ipmip_if_set_flags(&data->ipmip4.ipmip, proc, &iff->iff.ipmip, IP_IFF_UP); /**/ 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 assigned link-layer address for interface '%s'", iff->iff.ipmip.ifname)); } } } ipmipfa_llh_config_read(data, proc, iff); /* Do the external parsing */ for (i = IPMIPFA_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; } IP_GLOBAL void * ipmipfa_if_extension_data(Ipmipfa_iff_t *ifp, Ipmipfa_extension_t *ext) { if (ext->ifp_data_size == 0) return IP_NULL; return ifp->extdata[ext->func][ext->type]; } /* *=========================================================================== * ipmipfa_if_start *=========================================================================== * Description: Start an interface for a specified configuration. * Parameters: data - The FA entity. * proc - Current process. * Returns: * */ IP_GLOBAL void ipmipfa_if_stop(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_conf_t *conf) { Ipmipfa_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 = IPMIPFA_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); } } /* *=========================================================================== * ipmipfa_if_start *=========================================================================== * Description: Start an interface for a specified configuration. * Parameters: data - The FA entity. * proc - Current process. * Returns: * */ IP_GLOBAL void ipmipfa_if_start(Ipmipfa_data_t *data, Ipmip_proc_t *proc) { Ipmipfa_iff_t *iff; if (data->conf == IP_NULL) return; /* Send instant RtAdv on all active interfaces */ for (iff = IPCOM_LIST_FIRST(&data->conf->if_head); iff; 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)ipmipfa_if_advert_output_timeout, iff, IP_NULL, iff->adv_interval * 1000); } } } /* *=========================================================================== * ipmipfa_if_challenge_generate *=========================================================================== * Description: Generate a challenge * Parameters: data - Context * proc - Process * iff - The interface the challenge belongs to. * challenge - Where to store the challenge. * Returns: * */ IP_GLOBAL void ipmipfa_if_challenge_generate(Ipmipfa_data_t *data, Ipmip_proc_t *proc, Ipmipfa_iff_t *iff, Ip_u8 *challenge) { struct Ip_timeval tv; int i; IPMIP_UNUSED_PARAMETER(iff); IPMIP_UNUSED_PARAMETER(data); IPMIP_UNUSED_PARAMETER(proc); ipcom_microtime(&tv); ipcom_srandom((unsigned int) (tv.tv_sec + tv.tv_usec)); for (i = 0; i < IPMIPFA_CONF_CHALLENGE_LEN; i++) challenge[i] = (Ip_u8) ipcom_random(); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */