/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6pm_route.c,v $ $Revision: 1.16.10.1 $ * $Source: /home/interpeak/CVSRoot/ipmip6pm/src/ipmip6pm_route.c,v $ * $Author: svc-cmnet $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipmip6pm_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 "ipmip6pm_h.h" #include "ipmip6pm_pktbuf.h" #include "ipmip6pm_mh.h" #include "ipmip6pm_if.h" #include "ipmip6pm_node.h" #include "ipmip6pm_attr_h.h" #include "ipmip6pm_route.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ enum { IPMIP6PM_ROUTE_STATE_DO_ADD, IPMIP6PM_ROUTE_STATE_DO_DEL, IPMIP6PM_ROUTE_STATE_DO_GET }; #define IPMIP6PM_ROUTE_COA_SIZE(x) ((x) == IPMIP6_MIB_InetAddressType_ipv6? sizeof(struct Ip_in6_addr) : sizeof(Ip_u32)) #define IPMIP6PM_ROUTE_GRE_DOWNLINK(x) (IPMIP6PM_NODE_USE_GRE_KEYS(x)? &(x)->gre_key[IPMIP_LINK_DOWN] : IP_NULL) #define IPMIP6PM_ROUTE_GRE_UPLINK(x) (IPMIP6PM_NODE_USE_GRE_KEYS(x)? &(x)->gre_key[IPMIP_LINK_UP] : IP_NULL) /* **************************************************************************** * 5 TYPES **************************************************************************** */ typedef void (*Ipmip6pm_route_state_do_t) (struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ IP_STATIC void ipmip6pm_route_state_forward_ipv6_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_forward_ipv6_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_transport_ipv6_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_transport_ipv6_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_forward_ipv4_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_forward_ipv4_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_transport_ipv4_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); IP_STATIC void ipmip6pm_route_state_transport_ipv4_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd); /* **************************************************************************** * 8 DATA **************************************************************************** */ static Ipmip6pm_route_state_do_t ipmip6pm_route_states[IPMIP6PM_ROUTE_BIT_MAX] = { ipmip6pm_route_state_transport_ipv6_using_ipv6, ipmip6pm_route_state_transport_ipv6_using_ipv4, ipmip6pm_route_state_transport_ipv4_using_ipv6, ipmip6pm_route_state_transport_ipv4_using_ipv4, ipmip6pm_route_state_forward_ipv6_using_ipv6, ipmip6pm_route_state_forward_ipv6_using_ipv4, ipmip6pm_route_state_forward_ipv4_using_ipv6, ipmip6pm_route_state_forward_ipv4_using_ipv4, }; /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ IP_STATIC void ipmip6pm_route_state_forward_ipv6_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { Ip_u8 i; Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Create INBOUND route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_to, node->ifp_private.ipmip6.ifp->iff.ifindex, &node->mo_home_prefix[i].prefix, sizeof(struct Ip_in6_addr), node->mo_home_prefix[i].prefix_length, IP_NULL, 0, 0, ipmip_netlink_route_src_tunnel_in6(&scmp, &node->homeagent, IPMIP6PM_ROUTE_GRE_DOWNLINK(node)), &handle, IPMIP_LINK_RECV, IP_NULL, IPNET_RTF_CLONING); } break; case IPMIP6PM_ROUTE_STATE_DO_DEL: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Delete the INBOUND route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELROUTE, ctx->iftable_pm_to, 0,/* node->ifp_private.ipmip6.ifp->iff.ifindex, */ &node->mo_home_prefix[i].prefix, node->mo_home_prefix[i].prefix_length, IP_NULL, IP_RTN_UNICAST); } break; } } IP_STATIC void ipmip6pm_route_state_forward_ipv6_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET Ip_u8 i; Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Create INBOUND route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_to, node->ifp_private.ipmip6.ifp->iff.ifindex, &node->mo_home_prefix[i].prefix, sizeof(struct Ip_in6_addr), node->mo_home_prefix[i].prefix_length, IP_NULL, 0, 0, ipmip_netlink_route_src_tunnel_in(&scmp, node->homeagent_inet, IPMIP6PM_ROUTE_GRE_DOWNLINK(node)), &handle, IPMIP_LINK_RECV, IP_NULL, IPNET_RTF_CLONING); } break; case IPMIP6PM_ROUTE_STATE_DO_DEL: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Delete the INBOUND route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELROUTE, ctx->iftable_pm_to, 0,/* node->ifp_private.ipmip6.ifp->iff.ifindex, */ &node->mo_home_prefix[i].prefix, node->mo_home_prefix[i].prefix_length, IP_NULL, IP_RTN_UNICAST); } break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } IP_STATIC void ipmip6pm_route_state_transport_ipv6_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { Ip_u8 i; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Create OUTBOUND tunnel route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_home_prefix[i].prefix, sizeof(struct Ip_in6_addr), node->mo_home_prefix[i].prefix_length, &node->homeagent, sizeof(struct Ip_in6_addr), 0, IP_NULL, &handle, IPMIP_LINK_SEND, IPMIP6PM_ROUTE_GRE_UPLINK(node), IPNET_RTF_TUNNELEND); } break; case IPMIP6PM_ROUTE_STATE_DO_DEL: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Delete the OUTBOUND tunneling route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELROUTE, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_home_prefix[i].prefix, node->mo_home_prefix[i].prefix_length, IP_NULL, IP_RTN_UNICAST); } break; } } IP_STATIC void ipmip6pm_route_state_transport_ipv6_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET Ip_u8 i; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Create OUTBOUND tunnel route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_home_prefix[i].prefix, sizeof(struct Ip_in6_addr), node->mo_home_prefix[i].prefix_length, &node->homeagent_inet, sizeof(Ip_u32), node->homeagent_nat, IP_NULL, &handle, IPMIP_LINK_SEND, IPMIP6PM_ROUTE_GRE_UPLINK(node), IPNET_RTF_TUNNELEND); } break; case IPMIP6PM_ROUTE_STATE_DO_DEL: for (i = 0; i < node->mo_home_prefix_size; i++) { /* Delete the OUTBOUND tunneling route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELROUTE, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_home_prefix[i].prefix, node->mo_home_prefix[i].prefix_length, IP_NULL, IP_RTN_UNICAST); } break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } IP_STATIC void ipmip6pm_route_state_forward_ipv4_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET struct Ip_sockaddr_dl dl; void *nhop = IP_NULL; Ip_size_t nhop_size = 0; Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; if (node->lla != IP_NULL && node->ifp_private.ipmip6.ifp->iff.lladdr && node->lla->type == IPMIP_LLADDR_TYPE_MAC) { ipcom_memset(&dl, 0, sizeof(dl)); IPCOM_SA_LEN_SET(&dl, sizeof(struct Ip_sockaddr_dl)); dl.sdl_family = IP_AF_LINK; dl.sdl_index = node->ifp_private.ipmip6.ifp->iff.ifindex; dl.sdl_type = 0; dl.sdl_nlen = 0; dl.sdl_alen = IPMIP_LLADDR_LEN_LLA(node->lla); dl.sdl_slen = 0; if (dl.sdl_alen) ipcom_memcpy(IP_SOCKADDR_DL_LLADDR(&dl), IPMIP_LLADDR_DATA(node->lla), dl.sdl_alen); nhop = &dl; nhop_size = sizeof(dl); } switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_to, node->ifp_private.ipmip6.ifp->iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, sizeof(struct Ip_in_addr), 32, nhop, nhop_size, 0, ipmip_netlink_route_src_tunnel_in6(&scmp, &node->homeagent, IPMIP6PM_ROUTE_GRE_DOWNLINK(node)), &handle, IPMIP_LINK_RECV, IP_NULL, 0); break; case IPMIP6PM_ROUTE_STATE_DO_DEL: /* Delete the INBOUND route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELROUTE, ctx->iftable_pm_to, 0,/* node->ifp_private.ipmip6.ifp->iff.ifindex, */ &node->mo_dsmipv6_home_prefix.prefix, 32, IP_NULL, IP_RTN_UNICAST); break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } IP_STATIC void ipmip6pm_route_state_forward_ipv4_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET struct Ip_sockaddr_dl dl; void *nhop = IP_NULL; Ip_size_t nhop_size = 0; Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; if (node->lla != IP_NULL && node->ifp_private.ipmip6.ifp->iff.lladdr && node->lla->type == IPMIP_LLADDR_TYPE_MAC) { ipcom_memset(&dl, 0, sizeof(dl)); IPCOM_SA_LEN_SET(&dl, sizeof(struct Ip_sockaddr_dl)); dl.sdl_family = IP_AF_LINK; dl.sdl_index = node->ifp_private.ipmip6.ifp->iff.ifindex; dl.sdl_type = 0; dl.sdl_nlen = 0; dl.sdl_alen = IPMIP_LLADDR_LEN_LLA(node->lla); dl.sdl_slen = 0; if (dl.sdl_alen) ipcom_memcpy(IP_SOCKADDR_DL_LLADDR(&dl), IPMIP_LLADDR_DATA(node->lla), dl.sdl_alen); nhop = &dl; nhop_size = sizeof(dl); } switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_to, node->ifp_private.ipmip6.ifp->iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, sizeof(struct Ip_in_addr), 32, nhop, nhop_size, 0, ipmip_netlink_route_src_tunnel_in(&scmp, node->homeagent_inet, IPMIP6PM_ROUTE_GRE_DOWNLINK(node)), &handle, IPMIP_LINK_RECV, IP_NULL, 0); break; case IPMIP6PM_ROUTE_STATE_DO_DEL: /* Delete the INBOUND route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELROUTE, ctx->iftable_pm_to, 0,/* node->ifp_private.ipmip6.ifp->iff.ifindex, */ &node->mo_dsmipv6_home_prefix.prefix, 32, IP_NULL, IP_RTN_UNICAST); break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } IP_STATIC void ipmip6pm_route_state_transport_ipv4_using_ipv6(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: ipmip_netlink_route_src_ingress_ifindex(&scmp, node->ifp_private.ipmip6.ifp->iff.ifindex); /* Create OUTBOUND tunnel route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, sizeof(struct Ip_in_addr), 32, &node->homeagent, sizeof(struct Ip_in6_addr), 0, &scmp, &handle, IPMIP_LINK_SEND, IPMIP6PM_ROUTE_GRE_UPLINK(node), IPNET_RTF_TUNNELEND); break; case IPMIP6PM_ROUTE_STATE_DO_DEL: /* Delete the OUTBOUND tunneling route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELROUTE, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, 32, IP_NULL, IP_RTN_UNICAST); break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } IP_STATIC void ipmip6pm_route_state_transport_ipv4_using_ipv4(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, int docmd) { #ifdef IPMIP_USE_INET Ipmip_netlink_kern_compare_t scmp; Ipmip_netlink_kern_handle_t handle; handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; switch (docmd) { case IPMIP6PM_ROUTE_STATE_DO_ADD: ipmip_netlink_route_src_ingress_ifindex(&scmp, node->ifp_private.ipmip6.ifp->iff.ifindex); /* Create OUTBOUND tunnel route */ ipmip6_netlink_route_mip_do(&ctx->ipmip6, proc, IP_RTM_NEWMIP, IP_WRMOB6_NEW_LINK_TX, 0, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, sizeof(struct Ip_in_addr), 32, &node->homeagent_inet, sizeof(Ip_u32), node->homeagent_nat, &scmp, &handle, IPMIP_LINK_SEND, IPMIP6PM_ROUTE_GRE_UPLINK(node), IPNET_RTF_TUNNELEND); break; case IPMIP6PM_ROUTE_STATE_DO_DEL: /* Delete the OUTBOUND tunneling route */ ipmip_netlink_inX_route(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELROUTE, ctx->iftable_pm_from, node->ifp_public->iftunnels[node->transport_tunnel_type]->ipmip6.iff.ifindex, &node->mo_dsmipv6_home_prefix.prefix, 32, IP_NULL, IP_RTN_UNICAST); break; } #else IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); IPMIP_UNUSED_PARAMETER(docmd); IPMIP_UNUSED_PARAMETER(node); #endif } /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip6pm_route_state_add *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipmip6pm_route_state_add(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, Ip_u32 states) { unsigned int i; for (i = 0; i < IPMIP6PM_ROUTE_BIT_MAX; i++) { if (IPMIP6PM_ROUTE_STATE_CHECK(states,i) != 0) { if (IPMIP6PM_ROUTE_STATE_CHECK(node->route_state,i) == 0) { /* Time to enable this state */ (*ipmip6pm_route_states[i]) (ctx, proc, node, IPMIP6PM_ROUTE_STATE_DO_ADD); node->route_state |= IPMIP6PM_ROUTE_STATE_BIT(i); } } } } /* *=========================================================================== * ipmip6pm_route_state_del *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL void ipmip6pm_route_state_del(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node, Ip_u32 states) { unsigned int i; for (i = 0; i < IPMIP6PM_ROUTE_BIT_MAX; i++) { if (IPMIP6PM_ROUTE_STATE_CHECK(states,i) != 0) { if (IPMIP6PM_ROUTE_STATE_CHECK(node->route_state,i) != 0) { /* Time to enable this state */ (*ipmip6pm_route_states[i]) (ctx, proc, node, IPMIP6PM_ROUTE_STATE_DO_DEL); node->route_state &= ~IPMIP6PM_ROUTE_STATE_BIT(i); } } } } IP_GLOBAL void ipmip6pm_route_context_init(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc) { struct Ip_sioc_route_table iftable; ipcom_memset(&iftable, 0, sizeof(iftable)); iftable.table = IPCOM_ROUTE_TABLE_ANY; if (ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCADDROUTETAB, &iftable) < 0) { IPCOM_LOG2(ERR, "%s: ipcom_socketioctl(IP_SIOCADDROUTETAB) failed, errno = %d", ctx->ipmip6.ipmip.name, ipcom_errno); } ctx->iftable_pm_from = iftable.table; ipcom_memset(&iftable, 0, sizeof(iftable)); iftable.table = IPCOM_ROUTE_TABLE_ANY; if (ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCADDROUTETAB, &iftable) < 0) { IPCOM_LOG2(ERR, "%s: ipcom_socketioctl(IP_SIOCADDROUTETAB) failed, errno = %d", ctx->ipmip6.ipmip.name, ipcom_errno); } ctx->iftable_pm_to = iftable.table; #ifdef IPMIP_USE_INET ipcom_memset(&iftable, 0, sizeof(iftable)); iftable.table = IPCOM_ROUTE_TABLE_ANY; if (ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCADDROUTETAB, &iftable) < 0) { IPCOM_LOG2(ERR, "%s: ipcom_socketioctl(IP_SIOCADDROUTETAB) failed, errno = %d", ctx->ipmip6.ipmip.name, ipcom_errno); } ctx->iftable_pm_inet = iftable.table; #endif #ifdef IPMIP_USE_INET /* Add the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, ctx->iftable_pm_from, IPMIP6PM_ROUTE_PRIORITY_TUNNEL, 0, &ip_inaddr_any, 0, &ip_inaddr_any, 0, 0, IP_FIB_RULE_FIND_SADDR); /* Add the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_NEWRULE, ctx->iftable_pm_to, IPMIP6PM_ROUTE_PRIORITY_FORWARD, 0, &ip_inaddr_any, 0, &ip_inaddr_any, 0, 0, 0); #endif /* Add the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_NEWRULE, ctx->iftable_pm_from, IPMIP6PM_ROUTE_PRIORITY_TUNNEL, 0, &ip_in6addr_any, 0, &ip_in6addr_any, 0, 0, IP_FIB_RULE_FIND_SADDR); /* Add the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_NEWRULE, ctx->iftable_pm_to, IPMIP6PM_ROUTE_PRIORITY_FORWARD, 0, &ip_in6addr_any, 0, &ip_in6addr_any, 0, 0, 0); } IP_GLOBAL void ipmip6pm_route_context_destroy(struct Ipmip6pm_context *ctx, struct Ipmip_proc *proc) { struct Ip_sioc_route_table iftable; ipcom_memset(&iftable, 0, sizeof(iftable)); #ifdef IPMIP_USE_INET /* Delete the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, ctx->iftable_pm_from, IPMIP6PM_ROUTE_PRIORITY_TUNNEL, 0, &ip_inaddr_any, 0, &ip_inaddr_any, 0, 0, IP_FIB_RULE_FIND_SADDR); ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELRULE, ctx->iftable_pm_to, IPMIP6PM_ROUTE_PRIORITY_FORWARD, 0, &ip_inaddr_any, 0, &ip_inaddr_any, 0, 0, 0); #endif /* Delete the policy rule */ ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELRULE, ctx->iftable_pm_from, IPMIP6PM_ROUTE_PRIORITY_TUNNEL, 0, &ip_in6addr_any, 0, &ip_in6addr_any, 0, 0, IP_FIB_RULE_FIND_SADDR); ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELRULE, ctx->iftable_pm_to, IPMIP6PM_ROUTE_PRIORITY_FORWARD, 0, &ip_in6addr_any, 0, &ip_in6addr_any, 0, 0, 0); iftable.table = ctx->iftable_pm_from; /* Delete the route tables */ ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCDELROUTETAB, &iftable); iftable.table = ctx->iftable_pm_to; /* Delete the route tables */ ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCDELROUTETAB, &iftable); #ifdef IPMIP_USE_INET iftable.table = ctx->iftable_pm_inet; /* Delete the route tables */ ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCDELROUTETAB, &iftable); #endif } IP_GLOBAL int ipmip6pm_netlink_new_handle(Ipmip6pm_context_t *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node) { /**/ return ipmip6_netlink_new_handle(&ctx->ipmip6, proc, IPCOM_IPD_ID_IPMIP6PM, node->identity); } IP_GLOBAL int ipmip6pm_netlink_del_handle(Ipmip6pm_context_t *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node) { /**/ return ipmip6_netlink_del_handle(&ctx->ipmip6, proc, IPCOM_IPD_ID_IPMIP6PM, node->identity); } IP_GLOBAL Ip_bool ipmip6pm_netlink_get_handle_stat(Ipmip6pm_context_t *ctx, struct Ipmip_proc *proc, struct Ipmip6pm_node *node) { Ipmip6_netlink_kern_statistics_t link_recv, link_send; Ipmip_netlink_kern_handle_t handle; /* Identity */ handle.mip_facility = IPCOM_IPD_ID_IPMIP6PM; handle.mip_ident = node->identity; /* Retrieve the statistics; the SEND/RECV from the MIP4 point of view is * 'send tunnel' / 'receive tunnel', while from the node point of view * (statistics) is 'send from node' / 'send to node'. So, we have to * reverse the send/recv variables to get it right. */ if (ipmip6_netlink_get_handle_stat(&ctx->ipmip6, proc, &handle, &link_recv, &link_send)) { /* Update stats */ ipmip6_context_add_outbound(&ctx->ipmip6, link_send.mip_s_octets, link_send.mip_s_pkts); ipmip6pm_route_add_outbound(ctx, node, link_send.mip_s_octets, link_send.mip_s_pkts); ipmip6_context_add_inbound(&ctx->ipmip6, link_recv.mip_s_octets, link_recv.mip_s_pkts); ipmip6pm_route_add_inbound(ctx, node, link_recv.mip_s_octets, link_recv.mip_s_pkts); return IP_TRUE; } return IP_FALSE; } IP_GLOBAL void ipmip6pm_route_add_outbound(struct Ipmip6pm_context *ctx, struct Ipmip6pm_node *node, Ip_u64 octets, Ip_u64 pkts) { IPMIP_UNUSED_PARAMETER(ctx); IP_U64_ADD(node->mip6NodeTrafficEntry.mip6HCNodeOutOctets, octets); node->mip6NodeTrafficEntry.mip6NodeOutOctets = IP_U64_GETLO(node->mip6NodeTrafficEntry.mip6HCNodeOutOctets); IP_U64_ADD(node->mip6NodeTrafficEntry.mip6HCNodeOutPkts, pkts); node->mip6NodeTrafficEntry.mip6NodeOutPkts = IP_U64_GETLO(node->mip6NodeTrafficEntry.mip6HCNodeOutPkts); } IP_GLOBAL void ipmip6pm_route_add_inbound(struct Ipmip6pm_context *ctx, struct Ipmip6pm_node *node, Ip_u64 octets, Ip_u64 pkts) { IPMIP_UNUSED_PARAMETER(ctx); IP_U64_ADD(node->mip6NodeTrafficEntry.mip6HCNodeInOctets, octets); node->mip6NodeTrafficEntry.mip6NodeInOctets = IP_U64_GETLO(node->mip6NodeTrafficEntry.mip6HCNodeInOctets); IP_U64_ADD(node->mip6NodeTrafficEntry.mip6HCNodeInPkts, pkts); node->mip6NodeTrafficEntry.mip6NodeInPkts = IP_U64_GETLO(node->mip6NodeTrafficEntry.mip6HCNodeInPkts); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */