/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6ha_attr.c,v $ $Revision: 1.27 $ * $Source: /home/interpeak/CVSRoot/ipmip6ha/src/ipmip6ha_attr.c,v $ * $Author: jhorteli $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmip6ha_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 #include #include #include "ipmip6ha_h.h" #include "ipmip6ha_attr.h" #include "ipmip6ha_attr_h.h" #include "ipmip6ha_node.h" #include "ipmip6ha_nemo.h" #include "ipmip6ha_nemo_dsmipv6.h" #include "ipmip6ha_if.h" #include "ipmip6ha_route.h" #include "ipmip6ha_mag.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ struct Ipmip6ha_attr_op { Ipmip_cli_message_t *request; struct Ip_in6_addr *hoa; const char *nai_mn; Ip_size_t nai_mn_len; Ip_u32 ifindex; }; /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmipfa_node_del_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipmip6ha_attr_list_nodes(Ipmip6ha_context_t *ctx, Ipmip_proc_t *proc, Ipmip6ha_node_t *node, struct Ipmip6ha_attr_op *ops, void *unused) { IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(unused); if (ops->hoa != IP_NULL && !IP_IN6_ARE_ADDR_EQUAL(ops->hoa, &node->mip6BindingCacheEntry.mip6BindingHomeAddress.ipv6)) return; if (ops->nai_mn != IP_NULL && ops->nai_mn_len > 0) { /* Check NAI */ Ipmip6_mh_mo_nai_t *nai = (Ipmip6_mh_mo_nai_t *)node->nai_mn; if (!nai) return; /* Does the NAI match? */ if (!ipmip_util_strnnmatch(ops->nai_mn, ops->nai_mn_len, (char *)&nai->nai[0], (Ip_size_t)(nai->hdr.len - 1))) return; } if (ops->ifindex != 0 && ops->ifindex != node->ifp_home->ipmip6.iff.ifindex) return; /**/ ipmip_attr_put_u32(&ops->request->message, IPMIP6HA_CLI_ATTR_BC_X_HANDLE, node->identity); } /* *=========================================================================== * ipmip6ha_attr_node_dump *=========================================================================== * Description: Dump a node * Parameters: event - Current event * data - Data * proc - Current process * lock - Command locking structure * node - Node. * Returns: IP_FALSE * */ IP_STATIC int ipmip6ha_attr_node_dump(Ipmip6ha_context_t *ctx, Ipmip_proc_t *proc, Ipmip_cli_message_t *request, Ipmip6ha_node_t *node) { struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request); Ip_size_t rhdr = 0; Ip_size_t rta; if (node == IP_NULL) rhdr = ipmip_attr_hdr_err(&request->message, hdr, IP_ERRNO_ENOENT, IP_NULL); else { /**/ rhdr = ipmip_attr_hdr_ack(&request->message, hdr); /* Do retrieve statistics */ ipmip6ha_netlink_get_handle_stat(ctx, proc, node); /**/ rta = ipmip_attr_begin(&request->message, IPMIP6HA_CLI_ATTR_BC_X); /* */ if (!IP_IN6_IS_ADDR_UNSPECIFIED(&node->mip6BindingCacheEntry.mip6BindingHomeAddress.ipv6)) ipmip_attr_put_inet6(&request->message, IPMIP6HA_CLI_ATTR_BC_X_HOA_V6, &node->mip6BindingCacheEntry.mip6BindingHomeAddress.ipv6); /* Put the home address entry */ ipmip_attr_put_str(&request->message, IPMIP6HA_CLI_ATTR_BC_X_IFNAME,node->ifp_home->ipmip6.iff.ifname); ipmip_attr_put_time_t(&request->message, IPMIP6HA_CLI_ATTR_BC_X_UPDATED, node->updated); ipmip_attr_put_u32(&request->message, IPMIP6HA_CLI_ATTR_BC_X_REGFLAGS, node->regflags); ipmip_attr_put_u32(&request->message, IPMIP6HA_CLI_ATTR_BC_X_HANDLE, node->identity); if (node->nemo_v6.size > 0 #ifdef IPMIP_USE_INET || node->nemo_hoa_v4.size > 0 || node->nemo_prefix_v4.size > 0 #endif ) { Ipmip6ha_nemo_t *nemo; #ifdef IPMIP_USE_INET Ipmip6ha_nemo_dsmipv6_t *dsmipv6; #endif Ipmip_buffer_t pdata; ipmip_buffer_init(&pdata); for (nemo = IPCOM_LIST_FIRST(&node->nemo_v6); nemo != IP_NULL; nemo = IPCOM_LIST_NEXT(&nemo->next)) { Ipmip6_address_t address; ipcom_memcpy(&address.prefix, &nemo->prefix, sizeof(address.prefix)); address.len = nemo->len; ipmip_buffer_append(&pdata, &address, sizeof(address)); } if (IPMIP_BUFFER_SIZE(&pdata)) { ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_BC_X_PREFIX_V6,(Ip_u32)IPMIP_BUFFER_SIZE(&pdata),IPMIP_BUFFER_DATA(&pdata)); ipmip_buffer_shrink(&pdata, 0); } #ifdef IPMIP_USE_INET for (dsmipv6 = IPCOM_LIST_FIRST(&node->nemo_prefix_v4); dsmipv6 != IP_NULL; dsmipv6 = IPCOM_LIST_NEXT(&dsmipv6->next)) { Ipmip6_inet_t address; address.prefix = dsmipv6->prefix; address.len = (Ip_u8)dsmipv6->len; ipmip_buffer_append(&pdata, &address, sizeof(address)); } if (IPMIP_BUFFER_SIZE(&pdata)) { ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_BC_X_PREFIX_V4,(Ip_u32)IPMIP_BUFFER_SIZE(&pdata),IPMIP_BUFFER_DATA(&pdata)); ipmip_buffer_shrink(&pdata, 0); } for (dsmipv6 = IPCOM_LIST_FIRST(&node->nemo_hoa_v4); dsmipv6 != IP_NULL; dsmipv6 = IPCOM_LIST_NEXT(&dsmipv6->next)) ipmip_buffer_append(&pdata, &dsmipv6->prefix, sizeof(dsmipv6->prefix)); if (IPMIP_BUFFER_SIZE(&pdata)) { ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_BC_X_HOA_V4,(Ip_u32)IPMIP_BUFFER_SIZE(&pdata),IPMIP_BUFFER_DATA(&pdata)); ipmip_buffer_shrink(&pdata, 0); } #endif /* Free memory */ ipmip_buffer_release(&pdata); } /* Add the MO for MN NAI */ if (node->nai_mn != IP_NULL) ipmip_attr_put_strn(&request->message, IPMIP6HA_CLI_ATTR_BC_X_MOBILE_NAI,(char *)&((Ipmip6_mh_mo_nai_t *)node->nai_mn)->nai[0], (Ip_size_t)(node->nai_mn->len - 1)); /**/ ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_BC_X_MIB_mip6BindingCacheEntry, sizeof(node->mip6BindingCacheEntry), &node->mip6BindingCacheEntry); ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_BC_X_MIB_mip6NodeTrafficEntry, sizeof(node->mip6NodeTrafficEntry), &node->mip6NodeTrafficEntry); ipmip_attr_end(&request->message, rta); } /* If we have a reply header; terminate it */ ipmip_attr_hdr_finalize(&request->message, rhdr); /* Commit the reply */ ipmip_cli_message_commit(&ctx->ipmip6.ipmip, proc, request); return IPMIP_TIMER_RET_DONE; } /* *=========================================================================== * ipmip6ha_attr_node_delete *=========================================================================== * Description: Dump a node * Parameters: event - Current event * data - Data * proc - Current process * lock - Command locking structure * node - Node. * Returns: IP_FALSE * */ IP_STATIC int ipmip6ha_attr_node_delete(Ipmip6ha_context_t *ctx, Ipmip_proc_t *proc, Ipmip_cli_message_t *request, Ipmip6ha_node_t *node) { struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request); /**/ ipmip_attr_hdr_finalize(&request->message, ipmip_attr_hdr_ack(&request->message, hdr)); /* Commit the reply */ ipmip_cli_message_commit(&ctx->ipmip6.ipmip, proc, request); /* Terminate the node(s) */ ipmip6ha_node_delete(ctx, proc, node, "administrative termination"); return IPMIP_TIMER_RET_DONE; } /* *=========================================================================== * ipmip6ha_attr_node_delete *=========================================================================== * Description: Dump a node * Parameters: event - Current event * data - Data * proc - Current process * lock - Command locking structure * node - Node. * Returns: IP_FALSE * */ IP_STATIC int ipmip6ha_attr_node_revoke(Ipmip6ha_context_t *ctx, Ipmip_proc_t *proc, Ipmip_cli_message_t *request, Ipmip6ha_node_t *node, Ip_bool inet) { struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request); Ip_size_t rhdr = 0; int ret = IPMIP_TIMER_RET_DONE; if (node == IP_NULL) rhdr = ipmip_attr_hdr_err(&request->message, hdr, IP_ERRNO_ENOENT, IP_NULL); else { struct Ipmip_attr *rta_reason = ipmip_attr_hdr_find(hdr, IPMIP6HA_CLI_ATTR_BC_X_REVOKE_REASON); Ip_u8 reason = IPMIP6_MH_BRI_TRIGGER_ADMINISTRATIVE_REASON; /**/ if (rta_reason != IP_NULL) reason = (Ip_u8)ipmip_attr_get_u32(rta_reason); /**/ rhdr = ipmip_attr_hdr_ack(&request->message, hdr); /* Terminate the node(s) */ ret = ipmip6ha_node_revoke(ctx, proc, node, inet, reason, IP_NULL); } /* If we have a reply header; terminate it */ ipmip_attr_hdr_finalize(&request->message, rhdr); /* Commit the reply */ ipmip_cli_message_commit(&ctx->ipmip6.ipmip, proc, request); return ret; } /* *=========================================================================== * ipmip6mn_attr_network_dump *=========================================================================== * Description: Dump a node * Parameters: event - Current event * data - Data * proc - Current process * lock - Command locking structure * node - Node. * Returns: IP_FALSE * */ IP_STATIC int ipmip6ha_attr_node_do(int event, Ipmip6ha_context_t *ctx, Ipmip_proc_t *proc, Ipmip_cli_message_t *request, Ipmip6ha_node_t *node) { if (event == IPMIP_TIMER_EVENT_RUN) { struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request); switch (IPMIP_ATTR_HDR_TYPE(hdr)) { case IPMIP6HA_CLI_BC_X_GET: return ipmip6ha_attr_node_dump(ctx, proc, request, node); case IPMIP6HA_CLI_BC_X_DELETE: return ipmip6ha_attr_node_delete(ctx, proc, request, node); case IPMIP6HA_CLI_BC_X_REVOKE_NODE: return ipmip6ha_attr_node_revoke(ctx, proc, request, node, IP_FALSE); case IPMIP6HA_CLI_BC_X_REVOKE_NODE_INET: return ipmip6ha_attr_node_revoke(ctx, proc, request, node, IP_TRUE); } } else { /* Free the request */ ipmip_cli_message_free(&ctx->ipmip6.ipmip, proc, request); } /**/ return IPMIP_TIMER_RET_DONE; } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ IP_GLOBAL int ipmip6ha_attr_command(struct Ipmip6ha_context *ctx, struct Ipmip_proc *proc, struct Ipmip_cli_message *request) { struct Ipmip_attr_header *hdr = (struct Ipmip_attr_header *)IPMIP_BUFFER_DATA(&request->request); Ip_size_t rhdr = 0; struct Ipmip_attr *idattr[IPMIP6HA_CLI_ATTR_BC_X_MAX + 1]; switch (IPMIP_ATTR_HDR_TYPE(hdr)) { case IPMIP6HA_CLI_BC_X_LIST: { struct Ipmip6ha_attr_op aop; Ip_bool do_nai; ipcom_memset(&aop, 0, sizeof(aop)); aop.request = request; ipmip_attr_hdr_parse(IPMIP6HA_CLI_ATTR_BC_X_MAX, hdr, idattr); aop.hoa = ipmip_attr_get_inet6(idattr[IPMIP6HA_CLI_ATTR_BC_X_HOA_V6]); if (idattr[IPMIP6HA_CLI_ATTR_BC_X_IFNAME]) aop.ifindex = ipcom_if_nametoindex(ipmip_attr_get_str(idattr[IPMIP6HA_CLI_ATTR_BC_X_IFNAME])); /* NAI */ if (idattr[IPMIP6HA_CLI_ATTR_BC_X_MOBILE_NAI] != IP_NULL) { aop.nai_mn = IPMIP_ATTR_DATA(idattr[IPMIP6HA_CLI_ATTR_BC_X_MOBILE_NAI]); aop.nai_mn_len = IPMIP_ATTR_PAYLOAD(idattr[IPMIP6HA_CLI_ATTR_BC_X_MOBILE_NAI]); } rhdr = ipmip_attr_hdr_ack(&request->message, hdr); ipmip_context_id_lock(ctx->idents); ipmip_context_id_foreach(&ctx->ipmip6.ipmip, proc, ctx->idents, (Ipmip_util_hash_foreach_t)ipmip6ha_attr_list_nodes, &aop, &do_nai); ipmip_context_id_unlock(ctx->idents); } break; case IPMIP6HA_CLI_BC_X_GET: case IPMIP6HA_CLI_BC_X_DELETE: case IPMIP6HA_CLI_BC_X_REVOKE_NODE: case IPMIP6HA_CLI_BC_X_REVOKE_NODE_INET: { struct Ipmip_attr *rta_handle = ipmip_attr_hdr_find(hdr, IPMIP6HA_CLI_ATTR_BC_X_HANDLE); /**/ if (rta_handle == IP_NULL) return -IP_ERRNO_EINVAL; /* Get by identity */ ipmip6ha_node_lookup_handle(ctx, proc, ipmip_attr_get_u32(rta_handle), &request->timer, (Ipmip_timer_func_t)ipmip6ha_attr_node_do, request); return 0; } case IPMIP_CLI_NAME_LIST: rhdr = ipmip_attr_hdr_ack(&request->message, hdr); { /* Dump each configuration item we've currently got in human readable form */ Ipmip6ha_if_notify_t *notify; ipmip_attr_put_str(&request->message, IPMIP_CLI_ITEM_NAME, "global"); /* Clear any old interfaces */ for (notify = IPCOM_LIST_FIRST(&ctx->ifs); notify != IP_NULL; notify = IPCOM_LIST_NEXT(¬ify->next)) ipmip_attr_put_str(&request->message, IPMIP_CLI_ITEM_NAME, notify->ipmip6.ifp->iff.ifname); } break; case IPMIP_CLI_CONFIG_GET: rhdr = ipmip_attr_hdr_ack(&request->message, hdr); { /* Dump each configuration item we've currently got in human readable form */ Ipmip6ha_if_notify_t *notify; unsigned int si; struct Ipmip_attr *rta_name = ipmip_attr_hdr_find(hdr, IPMIP_CLI_ITEM_NAME); if (rta_name == IP_NULL || ipcom_strcasecmp("global", ipmip_attr_get_str(rta_name)) == 0) { for (si = 0; si < ctx->extensions_num; si++) { if (ctx->extensions[si]->config_global != IP_NULL && ctx->extdata[si] != IP_NULL) (*ctx->extensions[si]->config_global) (ctx, proc, IPMIP_CALLBACK_CONFIG_DUMP, ctx->extdata[si], request); } /* Dump the relay map */ ipmip6ha_dump_relay_map(ctx, proc, &request->message); } /* Clear any old interfaces */ for (notify = IPCOM_LIST_FIRST(&ctx->ifs); notify != IP_NULL; notify = IPCOM_LIST_NEXT(¬ify->next)) { Ipmip6ha_if_t *ife = (Ipmip6ha_if_t *)notify->ipmip6.ifp; if (rta_name != IP_NULL && ipcom_strcasecmp(ife->ipmip6.iff.ifname, ipmip_attr_get_str(rta_name)) != 0) continue; /**/ ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.lifetime=%d", ife->ipmip6.iff.ifname, ife->lifetime); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.refresh=%d", ife->ipmip6.iff.ifname, ife->refresh); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.homeagent=%s", ife->ipmip6.iff.ifname, ipmip_ntop_inet6(proc, &ife->ifaddr.prefix, IP_NULL)); #ifdef IPMIP_USE_INET ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.inet.homeagent=%s", ife->ipmip6.iff.ifname, ipmip_ntop_inet(proc, ife->ifaddr_v4)); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.tunnel.inet.ipip=%s", ife->ipmip6.iff.ifname, ife->ifenabled_H[IPMIP_TUNNELTYPE_IPIP]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.inet.tunnel.ipip=%s", ife->ipmip6.iff.ifname, ife->ifenabled_P[IPMIP_TUNNELTYPE_IPIP]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.inet.tunnel.gre=%s", ife->ipmip6.iff.ifname, ife->ifenabled_P[IPMIP_TUNNELTYPE_GRE]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.inet.AcceptForcedIPv4UDPEncapsulationRequest=%s", ife->ipmip6.iff.ifname, ife->AcceptForcedIPv4UDPEncapsulationRequest? "true" : "false"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.inet.ForceIPv4UDPEncapsulation=%s", ife->ipmip6.iff.ifname, ife->ForceIPv4UDPEncapsulation? "true" : "false"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.inet.IPv4UDPEncapsulationNATTimeout=%u", ife->ipmip6.iff.ifname, ife->IPv4UDPEncapsulationNATTimeout); #endif ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.AcceptUDPTLVEncapsulation=%s", ife->ipmip6.iff.ifname, ife->AcceptUDPTLVEncapsulation? "true" : "false"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.tunnel.ip6ip6=%s", ife->ipmip6.iff.ifname, ife->ifenabled_H[IPMIP_TUNNELTYPE_IP6IP6]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.BRIMaxRetriesNumber=%d", ife->ipmip6.iff.ifname, ife->BRIMaxRetriesNumber); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.BindingRevocation=%s", ife->ipmip6.iff.ifname, ife->BindingRevocationEnabled? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.MINDelayBRIs=%d", ife->ipmip6.iff.ifname, ife->MINDelayBRIs); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.tunnel.ip6ip6=%s", ife->ipmip6.iff.ifname, ife->ifenabled_P[IPMIP_TUNNELTYPE_IP6IP6]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.tunnel.gre=%s", ife->ipmip6.iff.ifname, ife->ifenabled_P[IPMIP_TUNNELTYPE_GRE6]? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.MinDelayBeforeBCEDelete=%d", ife->ipmip6.iff.ifname, ife->MinDelayBeforeBCEDelete); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.MaxDelayBeforeNewBCEAssign=%d", ife->ipmip6.iff.ifname, ife->MaxDelayBeforeNewBCEAssign); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.TimestampValidityWindow=%d", ife->ipmip6.iff.ifname, ife->TimestampValidityWindow); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.TimestampBasedApproachInUse=%d", ife->ipmip6.iff.ifname, ife->TimestampBasedApproachInUse? 1 : 0); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.LMA.MobileNodeGeneratedTimestampInUse=%d", ife->ipmip6.iff.ifname, ife->MobileNodeGeneratedTimestampInUse? 1 : 0); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.AlwaysVerifyTunnelSrc=%s", ife->ipmip6.iff.ifname, ife->AlwaysVerifyTunnelSrc? "enabled" : "disabled"); ipmip_cli_config_printf(&request->message, "ipmip6ha.interface.%s.RelayBindings=%s", ife->ipmip6.iff.ifname, ife->RelayBindings? "enabled" : "disabled"); ipmip6ha_mag_configure_dump(ctx, proc, ife, &request->message); ipmip6ha_nemo_dump_config(ctx, proc, ife->nemo, ife->ipmip6.iff.ifname, &request->message); for (si = 0; si < ctx->extensions_num; si++) { if (ctx->extensions[si]->config_ifp != IP_NULL) (*ctx->extensions[si]->config_ifp) (ctx, proc, IPMIP_CALLBACK_CONFIG_DUMP, ife, ctx->extdata[si], ife->extdata[si], request); } } } /* */ break; case IPMIP6HA_CLI_PREFIX_GET: rhdr = ipmip_attr_hdr_ack(&request->message, hdr); { Ipmip6ha_if_notify_t *notify; /* Clear any old interfaces */ for (notify = IPCOM_LIST_FIRST(&ctx->ifs); notify != IP_NULL; notify = IPCOM_LIST_NEXT(¬ify->next)) { Ipmip6ha_if_t *ifp = (Ipmip6ha_if_t *)notify->ipmip6.ifp; Ipmip6_if_prefix_t *prefix; Ipmip6_if_router_t *router; ipmip_timer_lock_acquire(&ctx->ipmip6.ipmip, proc, ifp->ipmip6.iff_lock); /* We have the address; do prefix matching */ for (router = IPCOM_LIST_FIRST(&ifp->ipmip6.routers); router != IP_NULL; router = IPCOM_LIST_NEXT(&router->next)) { for (prefix = IPCOM_LIST_FIRST(&router->prefixes); prefix != IP_NULL; prefix = IPCOM_LIST_NEXT(&prefix->next)) { if (IP_BIT_ISSET(prefix->flags, IPMIP6_ND_OPT_PI_FLAG_ONLINK)) { Ip_size_t rta = ipmip_attr_begin(&request->message, IPMIP6HA_CLI_ATTR_PREFIX); /* */ ipmip_attr_put(&request->message, IPMIP6HA_CLI_ATTR_PREFIX_PREFIX, sizeof(prefix->prefix), &prefix->prefix); ipmip_attr_put_inet6(&request->message, IPMIP6HA_CLI_ATTR_PREFIX_ROUTER, &router->addr); ipmip_attr_put_str(&request->message, IPMIP6HA_CLI_ATTR_PREFIX_IFNAME, ifp->ipmip6.iff.ifname); ipmip_attr_put_time_t(&request->message, IPMIP6HA_CLI_ATTR_PREFIX_VALID, prefix->valid); ipmip_attr_put_time_t(&request->message, IPMIP6HA_CLI_ATTR_PREFIX_TIMESTAMP, prefix->stamp); ipmip_attr_end(&request->message, rta); } } } ipmip_timer_lock_release(&ctx->ipmip6.ipmip, proc, ifp->ipmip6.iff_lock); } } break; case IPMIP6HA_CLI_MAG_GET: rhdr = ipmip_attr_hdr_ack(&request->message, hdr); { Ipmip6ha_if_notify_t *notify; /* Clear any old interfaces */ for (notify = IPCOM_LIST_FIRST(&ctx->ifs); notify != IP_NULL; notify = IPCOM_LIST_NEXT(¬ify->next)) ipmip6ha_mag_attr_get(ctx, proc, (Ipmip6ha_if_t *)notify->ipmip6.ifp, &request->message); } break; case IPMIP6HA_CLI_MAG_REVOKE: /* Must locate MAG and */ { const char *m_ifname = ipmip_attr_hdr_find_str(hdr, IPMIP6HA_CLI_ATTR_MAG_IFNAME); struct Ip_in6_addr *m_addr = ipmip_attr_hdr_find_inet6(hdr, IPMIP6HA_CLI_ATTR_MAG_ADDR_V6); Ipmip6ha_if_notify_t *notify; Ipmip6ha_if_t *ife; Ipmip6ha_mag_t *mag; /**/ if (m_ifname == IP_NULL || m_addr == IP_NULL) return -IP_ERRNO_EINVAL; for (notify = IPCOM_LIST_FIRST(&ctx->ifs); notify != IP_NULL; notify = IPCOM_LIST_NEXT(¬ify->next)) { ife = (Ipmip6ha_if_t *)notify->ipmip6.ifp; if (ipcom_strcasecmp(ife->ipmip6.iff.ifname, m_ifname) == 0) break; } if (notify == IP_NULL) return -IP_ERRNO_ENXIO; /* Time to find the MAG */ mag = ipmip6ha_mag_get(ctx, proc, ife, m_addr, 0); if (mag == IP_NULL) return -IP_ERRNO_ENOENT; /* Time to revoke */ ipmip6ha_mag_revoke(ctx, proc, mag, (Ip_u8)ipmip_attr_hdr_find_u32(hdr, IPMIP6HA_CLI_ATTR_MAG_REASON), ipmip_attr_hdr_find_str(hdr, IPMIP6HA_CLI_ATTR_MAG_MATCH)); /* Must release */ ipmip6ha_mag_release(ctx, proc, mag); rhdr = ipmip_attr_hdr_ack(&request->message, hdr); } break; default: /**/ return ipmip6_attr_command(&ctx->ipmip6, proc, request); } /* If we have a reply header; terminate it */ ipmip_attr_hdr_finalize(&request->message, rhdr); /* Commit the reply */ ipmip_cli_message_commit(&ctx->ipmip6.ipmip, proc, request); return 0; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */