/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6_ipsec.c,v $ $Revision: 1.8.16.1 $ * $Source: /home/interpeak/CVSRoot/ipmip6/src/ipmip6_ipsec.c,v $ * $Author: jhorteli $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmip6_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include "ipmip6_h.h" #include #include #include #include /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip6_ipsec_key_parse *=========================================================================== * Description: Parse a key based on the string description. * Parameters: context - The context * key - Where to store the key. * kstr - The string description * Returns: IP_TRUE if successful. * */ IP_STATIC Ip_bool ipmip6_ipsec_key_parse(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_key_t *key, char *kstr) { Ip_u32 len; IPMIP_UNUSED_PARAMETER(proc); if (ipcom_strncasecmp(kstr, "0x", 2) == 0) { Ip_u32 i; /* Skip the '0x' */ kstr += 2; /* Each two bytes are a hex value */ len = ipcom_strlen(kstr); len >>= 1; /* Create key */ key->iik_key = ipcom_malloc(len); key->iik_key_len = len; if (key->iik_key == IP_NULL) { IPCOM_LOG1(CRIT, "%s: IPSEC Failed to allocate memory for SA Key", ctx->ipmip.name); return IP_FALSE; } for (i = 0; i < len; i++) { unsigned int value; char buf[3]; /* Copy the first two bytes */ ipcom_strncpy(buf, kstr, sizeof(buf)); /* Parse them */ value = ipcom_strtoul(buf, IP_NULL, 16); /* Store the value */ key->iik_key[i] = (Ip_u8) value; /* Read next two */ kstr += 2; } } else { /* Calculate the length */ len = ipcom_strlen(kstr); /* */ key->iik_key = (Ip_u8 *)ipcom_strdup(kstr); key->iik_key_len = len; if (key->iik_key == IP_NULL) { IPCOM_LOG1(CRIT, "%s: IPSEC Failed to allocate memory for SA Key", ctx->ipmip.name); return IP_FALSE; } } return IP_TRUE; } /* *=========================================================================== * ipmip6_ipsec_find_spi *=========================================================================== * Description: Locate a specific SA based on SPI * Parameters: sa - The SA * spi - The SPI to look for. * Returns: * */ IP_STATIC Ipmip6_ipsec_sa_t * ipmip6_ipsec_find_spi(Ipcom_list *sas, Ip_u32 spi) { Ipmip6_ipsec_sa_t *sa; for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = IPCOM_LIST_NEXT(&sa->iis_next)) if (sa->iis_spi == spi) return sa; /* Do they match? */ return IP_NULL; } /* *=========================================================================== * ipmip6_ipsec_move_flow_dst *=========================================================================== * Description: Move the the peer destination endpoint in the flow * Parameters: flow - The flow * peer - The peer * Returns: IP_TRUE * */ IP_STATIC Ip_bool ipmip6_ipsec_move_flow_dst(Ipmip6_ipsec_flow_t *flow, struct Ip_in6_addr *peer) { ipcom_memcpy(&flow->iif_dst, peer, sizeof(*peer)); ipcom_memcpy(&flow->iif_dst_mask, &ipmip6_in6addr_allmask, sizeof(ipmip6_in6addr_allmask)); return IP_TRUE; } /* *=========================================================================== * ipmip6_ipsec_move_flow_src *=========================================================================== * Description: Move the the peer source endpoint in the flow * Parameters: flow - The flow * peer - The peer * Returns: IP_TRUE * */ IP_STATIC Ip_bool ipmip6_ipsec_move_flow_src(Ipmip6_ipsec_flow_t *flow, struct Ip_in6_addr *peer) { ipcom_memcpy(&flow->iif_src, peer, sizeof(*peer)); ipcom_memcpy(&flow->iif_src_mask, &ipmip6_in6addr_allmask, sizeof(ipmip6_in6addr_allmask)); return IP_TRUE; } /* *=========================================================================== * ipmip6_ipsec_free *=========================================================================== * Description: Delete all memory associated with a SA * Parameters: sa - The SA * Returns: * */ IP_STATIC void ipmip6_ipsec_free(Ipmip6_ipsec_sa_t *sa) { if (sa->iis_auth.iik_mode != IP_NULL) ipcom_free(sa->iis_auth.iik_mode); if (sa->iis_auth.iik_key != IP_NULL) ipcom_free(sa->iis_auth.iik_key); if (sa->iis_enc.iik_mode != IP_NULL) ipcom_free(sa->iis_enc.iik_mode); if (sa->iis_enc.iik_key != IP_NULL) ipcom_free(sa->iis_enc.iik_key); ipcom_free(sa); } /* *=========================================================================== * ipmip6_ipsec_reference *=========================================================================== * Description: Increase the reference count for the SA. * Parameters: sa - The SA. * Returns: * */ IP_STATIC void ipmip6_ipsec_reference(Ipmip6_ipsec_sa_t *sa, Ipmip6_ipsec_flow_t *flow) { /* Insert the flow */ ipcom_list_insert_first(&sa->iis_flows, &flow->iif_next); ++sa->iis_references; } /* *=========================================================================== * ipmip6_ipsec_dereference *=========================================================================== * Description: Decrease the reference count for the SA. Deletes the SA * if it reaches zero. * Parameters: sa - The SA. * Returns: * */ IP_STATIC void ipmip6_ipsec_dereference(Ipmip6_ipsec_sa_t *sa, Ipmip6_ipsec_flow_t *flow) { /* Remove the flow from the linked list */ ipcom_list_remove(&flow->iif_next); --sa->iis_references; } /* *=========================================================================== * ipmip6_ipsec_install *=========================================================================== * Description: Installs a SA if required. * Parameters: sa - The SA to install. * Returns: IP_TRUE if successful. * */ IP_STATIC Ip_bool ipmip6_ipsec_install(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_sa_t *sa) { if (sa->iis_installed == 0) { /* Not yet installed */ if (ipmip6_port_ipsec_install(ctx, proc, sa) == IP_FALSE) return IP_FALSE; } /* Increase the installed count */ sa->iis_installed++; /* Already installed */ return IP_TRUE; } /* *=========================================================================== * ipmip6_ipsec_uninstall *=========================================================================== * Description: Uninstalls a SA if there are no more installed references. * Parameters: * Returns: * */ IP_STATIC void ipmip6_ipsec_uninstall(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_sa_t *sa) { /* Is it installed at all? */ if (sa->iis_installed > 0) { /* Was this the last reference? */ if (--sa->iis_installed == 0) { /* Apparently, remove it */ ipmip6_port_ipsec_uninstall(ctx, proc, sa); } } } /* *=========================================================================== * ipmip6_ipsec_uninstall_flow *=========================================================================== * Description: Uninstall a flow. * Parameters: flow - The flow to uninstall. * Returns: * */ IP_STATIC void ipmip6_ipsec_uninstall_flow(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_flow_t *flow) { /* Is it installed? */ if (flow->iif_installed) { /* Do a port removal of this flow */ ipmip6_port_ipsec_uninstall_flow(ctx, proc, flow); /* Mark it as uninstalled */ flow->iif_installed = IP_FALSE; /* Uninstall the SA */ ipmip6_ipsec_uninstall(ctx, proc, flow->iif_sa); } } /* *=========================================================================== * ipmip6_ipsec_install_flow *=========================================================================== * Description: Install a flow. * Parameters: flow - The flow to install. * Returns: * */ IP_STATIC Ip_bool ipmip6_ipsec_install_flow(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_flow_t *flow) { /* Is it installed? */ if (flow->iif_sa != IP_NULL && flow->iif_installed == IP_FALSE) { /* Install the SA */ if (ipmip6_ipsec_install(ctx, proc, flow->iif_sa)) { /* Do a port removal of this flow */ if (ipmip6_port_ipsec_install_flow(ctx, proc, flow)) { /* Mark it as uninstalled */ flow->iif_installed = IP_TRUE; return IP_TRUE; } /* Failed to install the flow, deinstall the SA */ ipmip6_ipsec_uninstall(ctx, proc, flow->iif_sa); } } /* No go */ return IP_FALSE; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip6_ipsec_setup_flow *=========================================================================== * Description: Setup a flow * Parameters: flow - The flow to setup. * spi - The spi number. * direction - IPMIP6_IPSEC_SA_DIR_IN or IPMIP6_IPSEC_SA_DIR_OUT * endpoint - IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE or * IPMIP6_IPSEC_SA_ENDPOINT_STATIC * protocol - The protocol * mode - IPMIP6_IPSEC_SA_MODE_TRANSPORT or * IPMIP6_IPSEC_SA_MODE_TUNNEL * dst - Destination address * dst_mask - Destination mask * src - Source address * src_mask - Source mask * ife - Interface pointer. * Returns: * */ IP_GLOBAL void ipmip6_ipsec_setup_flow(Ipmip6_ipsec_flow_t *flow, Ip_u32 spi, Ip_u8 direction, Ip_u8 endpoint, Ip_u8 protocol, Ip_u8 mode, const struct Ip_in6_addr *dst, const struct Ip_in6_addr *dst_mask, const struct Ip_in6_addr *src, const struct Ip_in6_addr *src_mask, struct Ipmip6_if *ife) { /* Set base information */ flow->iif_spi = spi; flow->iif_dir = direction; flow->iif_endpoint = endpoint; flow->iif_protocol = protocol; flow->iif_mode = mode; /* Store the addresses */ if (dst) ipcom_memcpy(&flow->iif_dst, dst, sizeof(struct Ip_in6_addr)); if (dst_mask) ipcom_memcpy(&flow->iif_dst_mask, dst_mask, sizeof(struct Ip_in6_addr)); if (src) ipcom_memcpy(&flow->iif_src, src, sizeof(struct Ip_in6_addr)); if (src_mask) ipcom_memcpy(&flow->iif_src_mask, src_mask, sizeof(struct Ip_in6_addr)); /* Store the interface */ flow->iif_if = ife; } /* *=========================================================================== * ipmip6_ipsec_load_sa *=========================================================================== * Description: Load an SA and store it into the specified list. * Parameters: * Returns: * */ IP_GLOBAL Ip_bool ipmip6_ipsec_load_sa(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas, Ip_u32 spi, const char *product, const char *configuration, const char *feature) { Ipmip6_ipsec_sa_t *sa; /* Try locate it among the already existing */ if (ipmip6_ipsec_find_spi(sas, spi) == IP_NULL) { static Ipmip_sysvar_key_map_t transport[] = { { IPMIP6_IPSEC_SA_PROTOCOL_ESP, "esp" }, { IPMIP6_IPSEC_SA_PROTOCOL_AH, "ah" }, { 0, 0 } }; int i; char *ikey; /* Allocate new SA */ sa = ipcom_calloc(1, sizeof(*sa)); if (sa == IP_NULL) { IPCOM_LOG1(CRIT, "%s: IPSEC Failed to allocate memory for SA", ctx->ipmip); return IP_FALSE; } /* Init the flow list */ ipcom_list_init(&sa->iis_flows); /* Store the SPI value */ sa->iis_spi = spi; if ((i = ipmip_sysvar_key(-1, transport, "%s.%s.%s.%u.transport", product, configuration, feature, spi)) != -1 || (i = ipmip_sysvar_key(-1, transport, "%s.%s.%s.transport", product, configuration, feature)) != -1) sa->iis_protocol = (Ip_u8)i; /* Create the Auth algorithm key */ if ((ikey = ipmip_sysvar("%s.%s.%s.%u.authmode", product, configuration, feature, spi)) == IP_NULL && (ikey = ipmip_sysvar("%s.%s.%s.authmode", product, configuration, feature)) == IP_NULL) { IPCOM_LOG2(CRIT, "%s: IPSEC missing/invalid 'authalg' for SPI=%u", ctx->ipmip.name, spi); goto failed; } /* Save the key */ sa->iis_auth.iik_mode = ikey; /* Create the Auth algorithm key */ if ((ikey = ipmip_sysvar("%s.%s.%s.%u.authkey", product, configuration, feature, spi)) == IP_NULL && (ikey = ipmip_sysvar("%s.%s.%s.authkey", product, configuration, feature)) == IP_NULL) { IPCOM_LOG2(CRIT, "%s: IPSEC missing/invalid 'authkey' for SPI=%u", ctx->ipmip.name, spi); goto failed; } /* Parse the key */ if (ipmip6_ipsec_key_parse(ctx, proc, &sa->iis_auth, ikey) == IP_FALSE) { ipcom_free(ikey); goto failed; } ipcom_free(ikey); /* Create the Enc algorithm key */ if ((ikey = ipmip_sysvar("%s.%s.%s.%u.encmode", product, configuration, feature, spi)) == IP_NULL && (ikey = ipmip_sysvar("%s.%s.%s.encmode", product, configuration, feature)) == IP_NULL) { IPCOM_LOG2(CRIT, "%s: IPSEC missing/invalid 'encalg' for SPI=%u", ctx->ipmip.name, spi); goto failed; } sa->iis_enc.iik_mode = ikey; /* Create the Auth algorithm key */ if ((ikey = ipmip_sysvar("%s.%s.%s.%u.enckey", product, configuration, feature, spi)) == IP_NULL && (ikey = ipmip_sysvar("%s.%s.%s.enckey", product, configuration, feature)) == IP_NULL) { IPCOM_LOG2(CRIT, "%s: IPSEC missing/invalid 'enckey' for SPI=%u", ctx->ipmip.name, spi); goto failed; } /* Parse the key */ if (ipmip6_ipsec_key_parse(ctx, proc, &sa->iis_enc, ikey) == IP_FALSE) { ipcom_free(ikey); goto failed; } ipcom_free(ikey); /* We've built ourselves a SA */ ipcom_list_insert_first(sas, &sa->iis_next); } return IP_TRUE; failed: /* Failed to create the SA */ ipmip6_ipsec_free(sa); return IP_FALSE; } /* *=========================================================================== * ipmip6_ipsec_attach_flow *=========================================================================== * Description: Reads the ipsec parameters from the sysvar interface * based on a given mask. * Parameters: sas - SA list * flow - The flow key to configure. * Returns: * */ IP_GLOBAL Ip_bool ipmip6_ipsec_attach_flow(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas, Ipmip6_ipsec_flow_t *flow) { Ipmip6_ipsec_sa_t *sa; IPMIP_UNUSED_PARAMETER(proc); /* Try locate it among the already existing */ if ((sa = ipmip6_ipsec_find_spi(sas, flow->iif_spi)) == IP_NULL) return IP_FALSE; /* Store the SA */ flow->iif_sa = sa; ipmip6_ipsec_reference(sa, flow); /* Direction mismatch? */ if (sa->iis_dir != flow->iif_dir) { /* Mark it, if unspecified */ if (sa->iis_dir == 0) { /* Mark it with the same direction as the flow */ sa->iis_dir = flow->iif_dir; } else { IPCOM_LOG4(CRIT, "%s: IPSEC %s flow cannot attach to %s SA [SPI=%u]", ctx->ipmip.name, flow->iif_dir == IPMIP6_IPSEC_SA_DIR_IN? "inbound" : "outbound", sa->iis_dir == IPMIP6_IPSEC_SA_DIR_IN? "inbound" : "outbound", flow->iif_spi); ipmip6_ipsec_dereference(sa, flow); return IP_FALSE; } } /* Moveable? */ if (sa->iis_endpoint != flow->iif_endpoint) { /* Current definition */ if (sa->iis_endpoint == 0) { /* Mark it with the same moveability as the flow */ sa->iis_endpoint = flow->iif_endpoint; } else { IPCOM_LOG4(CRIT, "%s: IPSEC %s flow cannot attach to %s SA [SPI=%u]", ctx->ipmip.name, flow->iif_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE? "moveable" : "static", sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE? "moveable" : "static", flow->iif_spi); ipmip6_ipsec_dereference(sa, flow); return IP_FALSE; } } /* Verify that mode is correct */ if (sa->iis_mode != flow->iif_mode) { if (sa->iis_mode == 0) { /* Mark it with the same mode as the flow */ sa->iis_mode = flow->iif_mode; } else { IPCOM_LOG4(CRIT, "%s: IPSEC %s mode flow cannot attach to %s mode SA [SPI=%u]", ctx->ipmip.name, flow->iif_mode == IPMIP6_IPSEC_SA_MODE_TRANSPORT? "transport" : "tunnel", sa->iis_mode == IPMIP6_IPSEC_SA_MODE_TRANSPORT? "transport" : "tunnel", flow->iif_spi); ipmip6_ipsec_dereference(sa, flow); return IP_FALSE; } } /* Works */ return IP_TRUE; } /* *=========================================================================== * ipmip6_ipsec_detach_flow *=========================================================================== * Description: Detach a flow. * Parameters: flow - The flow * Returns: * */ IP_GLOBAL void ipmip6_ipsec_detach_flow(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipmip6_ipsec_flow_t *flow) { if (flow->iif_sa != IP_NULL) { /* Uninstall the flow */ ipmip6_ipsec_uninstall_flow(ctx, proc, flow); /* Dereference the SA */ ipmip6_ipsec_dereference(flow->iif_sa, flow); } } /* *=========================================================================== * ipmip6_ipsec_move_sa_coa *=========================================================================== * Description: Move the endpoint of all moveable SA's * Parameters: sa - The list of SA's * coa - The new CoA. * Returns: * */ IP_GLOBAL void ipmip6_ipsec_move_sa_coa(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas, struct Ip_in6_addr *coa) { Ipmip6_ipsec_sa_t *sa, *nsa; IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); /* Go through the list */ for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { nsa = IPCOM_LIST_NEXT(&sa->iis_next); /* Only touch moveable endpoints */ if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE) { /* Depending on direction */ if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_IN) { /* Inbound SA. The destination is the COA */ ipcom_memcpy(&sa->iis_dst, coa, sizeof(*coa)); } else if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_OUT) { /* Outbound SA. The source is the COA */ ipcom_memcpy(&sa->iis_src, coa, sizeof(*coa)); } } } } /* *=========================================================================== * ipmip6_ipsec_move_sa_peer *=========================================================================== * Description: Move the peer endpoint of all SA's * Parameters: sa - The list of SA's * peer - The new peer. * Returns: * */ IP_GLOBAL void ipmip6_ipsec_move_sa_peer(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas, struct Ip_in6_addr *peer) { Ipmip6_ipsec_sa_t *sa, *nsa; IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); /* Go through the list */ for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { Ipmip6_ipsec_flow_t *flow, *nflow; nsa = IPCOM_LIST_NEXT(&sa->iis_next); /* Depending on direction */ if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_IN) { /* Inbound SA. The source is the peer */ ipcom_memcpy(&sa->iis_src, peer, sizeof(*peer)); /* Repoint static flows */ if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { /* Inbound, set flow destination */ for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_move_flow_src(flow, peer); } } } else if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_OUT) { /* Outbound SA. destination is the peer */ ipcom_memcpy(&sa->iis_dst, peer, sizeof(*peer)); if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { /* Inbound, set flow destination */ for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_move_flow_dst(flow, peer); } } } } } /* *=========================================================================== * ipmip6_ipsec_move_sa_home *=========================================================================== * Description: Move the home endpoint of all SA's * Parameters: sa - The list of SA's * home - The new home. * Returns: * */ IP_GLOBAL void ipmip6_ipsec_move_sa_home(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas, struct Ip_in6_addr *home) { Ipmip6_ipsec_sa_t *sa, *nsa; IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); /* Go through the list */ for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { Ipmip6_ipsec_flow_t *flow, *nflow; nsa = IPCOM_LIST_NEXT(&sa->iis_next); /* Depending on direction */ if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_IN) { if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { /* Inbound SA. The destination is home if it's static */ ipcom_memcpy(&sa->iis_dst, home, sizeof(*home)); } /* Inbound, set flow destination */ for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_move_flow_dst(flow, home); } } else if (sa->iis_dir == IPMIP6_IPSEC_SA_DIR_OUT) { if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { /* Outbound SA. The source should be home if it's static */ ipcom_memcpy(&sa->iis_src, home, sizeof(*home)); } /* Outbound, set flow source */ for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_move_flow_src(flow, home); } } } } /* *=========================================================================== * ipmip6_ipsec_install_sa_moveable *=========================================================================== * Description: Installs all moveable SA's and their attached flows. * Parameters: sas - The list of SA's * Returns: * */ IP_GLOBAL void ipmip6_ipsec_install_sa_moveable(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas) { Ipmip6_ipsec_sa_t *sa, *nsa; for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { nsa = IPCOM_LIST_NEXT(&sa->iis_next); /* Only touch moveable endpoints */ if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE) { Ipmip6_ipsec_flow_t *flow, *nflow; for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_install_flow(ctx, proc, flow); } } } } /* *=========================================================================== * ipmip6_ipsec_uninstall_sa_moveable *=========================================================================== * Description: Uninnstalls all moveable SA's and their attached flows. * Parameters: sas - The list of SA's * Returns: * */ IP_GLOBAL void ipmip6_ipsec_uninstall_sa_moveable(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas) { Ipmip6_ipsec_sa_t *sa, *nsa; for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { nsa = IPCOM_LIST_NEXT(&sa->iis_next); if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_MOVEABLE) { Ipmip6_ipsec_flow_t *flow, *nflow; for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_uninstall_flow(ctx, proc, flow); } } } } /* *=========================================================================== * ipmip6_ipsec_install_sa_static *=========================================================================== * Description: Installs all static SA's and their attached flows. * Parameters: sas - The list of SA's * Returns: * */ IP_GLOBAL void ipmip6_ipsec_install_sa_static(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas) { Ipmip6_ipsec_sa_t *sa, *nsa; for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { nsa = IPCOM_LIST_NEXT(&sa->iis_next); if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { Ipmip6_ipsec_flow_t *flow, *nflow; for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_install_flow(ctx, proc, flow); } } } } /* *=========================================================================== * ipmip6_ipsec_delete_sa *=========================================================================== * Description: Delete all SAS in a specified list. * Parameters: sas - The list. * Returns: * */ IP_GLOBAL void ipmip6_ipsec_delete_sa(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas) { Ipmip6_ipsec_sa_t *sa; /* Make certain it's all uninstalled */ ipmip6_ipsec_uninstall_sa_moveable(ctx, proc, sas); ipmip6_ipsec_uninstall_sa_static(ctx, proc, sas); /* Remove all SAS */ while ((sa = IPCOM_LIST_FIRST(sas)) != IP_NULL) { /* Remove STATIC endpoints */ ipmip6_ipsec_uninstall(ctx, proc, sa); /* Go */ ipcom_list_remove(&sa->iis_next); ipmip6_ipsec_free(sa); } } /* *=========================================================================== * ipmip6_ipsec_uninstall_sa_static *=========================================================================== * Description: Uninstalls all static SA's and their attached flows. * Parameters: sas - The list of SA's * Returns: * */ IP_GLOBAL void ipmip6_ipsec_uninstall_sa_static(Ipmip6_context_t *ctx, Ipmip_proc_t *proc, Ipcom_list *sas) { Ipmip6_ipsec_sa_t *sa, *nsa; for (sa = IPCOM_LIST_FIRST(sas); sa != IP_NULL; sa = nsa) { nsa = IPCOM_LIST_NEXT(&sa->iis_next); if (sa->iis_endpoint == IPMIP6_IPSEC_SA_ENDPOINT_STATIC) { Ipmip6_ipsec_flow_t *flow, *nflow; for (flow = IPCOM_LIST_FIRST(&sa->iis_flows); flow != IP_NULL; flow = nflow) { nflow = IPCOM_LIST_NEXT(&flow->iif_next); ipmip6_ipsec_uninstall_flow(ctx, proc, flow); } } } } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */