2244 lines
92 KiB
C
2244 lines
92 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6mn_route.c,v $ $Revision: 1.36.2.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip6mn/src/ipmip6mn_route.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipmip6mn_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_ipd.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_shell.h>
|
|
|
|
#include <ipnet.h>
|
|
#include <ipnet_policy_routing.h>
|
|
|
|
#include <ipmip.h>
|
|
#include <private/ipmip_util.h>
|
|
|
|
#include <ipmip6.h>
|
|
#include <private/ipmip6_netlink.h>
|
|
#include <private/ipmip6_pkt.h>
|
|
#include <private/ipmip6_util.h>
|
|
|
|
#include "ipmip6mn_h.h"
|
|
#include "ipmip6mn_route.h"
|
|
#include "ipmip6mn_attr_h.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
enum
|
|
{
|
|
IPMIP6MN_ROUTE_DO_ADD,
|
|
IPMIP6MN_ROUTE_DO_DEL,
|
|
};
|
|
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
#define IPMIP6MN_ROUTE_LOCAL(ifp) ((ifp)->tun.family == IP_AF_INET6? (void *)&(ifp)->tun.local.in6 : (void *)&(ifp)->tun.local.in.s_addr)
|
|
#define IPMIP6MN_ROUTE_ENDPOINT(ifp) ((ifp)->tun.family == IP_AF_INET6? (void *)&(ifp)->tun.remote_inet6 : (void *)&(ifp)->tun.remote_inet)
|
|
#define IPMIP6MN_ROUTE_ENDPOINT_SIZE(ifp) (Ip_size_t)((ifp)->tun.family == IP_AF_INET6? sizeof(struct Ip_in6_addr) : sizeof(struct Ip_in_addr))
|
|
#define IPMIP6MN_ROUTE_SIZE(ifp) (Ip_size_t)((ifp)->tun.family == IP_AF_INET6? sizeof(struct Ip_in6_addr) : sizeof(struct Ip_in_addr))
|
|
#define IPMIP6MN_ROUTE_ENDPOINT_PORT(ifp,encap) (Ip_u32) ((encap)? ip_htons(IPMIP6_DSMIP_UDP_PORT) : 0)
|
|
#define IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(ifp) IPMIP6MN_ROUTE_ENDPOINT_PORT(ifp, (ifp)->tun.remote_transport_udp_encapsulate)
|
|
#else
|
|
#define IPMIP6MN_ROUTE_LOCAL(ifp) ((void *)&(ifp)->tun.local.in6)
|
|
#define IPMIP6MN_ROUTE_ENDPOINT(ifp) (&(ifp)->tun.remote_inet6)
|
|
#define IPMIP6MN_ROUTE_SIZE(ifp) (sizeof(struct Ip_in6_addr))
|
|
#define IPMIP6MN_ROUTE_ENDPOINT_PORT(ifp, nat) (0)
|
|
#define IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(ifp) (0)
|
|
#endif
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipmip6mn_route_tunnel
|
|
{
|
|
Ipmip6_if_t iff6;
|
|
|
|
int route_type; /* Current state */
|
|
int route_state; /* Current state */
|
|
|
|
Ip_u32 rtable;
|
|
Ip_u32 btable;
|
|
Ip_u32 htable; /* Home agent routing table */
|
|
|
|
Ip_u32 nemo_table; /* NEMO routing table */
|
|
Ip_u32 nemo_stats; /* NEMO routing table */
|
|
|
|
struct Ip_in6_addr inet6; /* Home Address */
|
|
#ifdef IPMIP_USE_INET
|
|
Ip_u32 inet;
|
|
Ip_u32 inet_plen;
|
|
#endif
|
|
/**/
|
|
struct Ipmip6mn_node *node;
|
|
|
|
/* Current home agent policy route */
|
|
struct
|
|
{
|
|
Ip_u8 family;
|
|
union Ip_in_addr_union local;
|
|
struct Ip_in6_addr remote_inet6;
|
|
Ip_u32 remote_inet;
|
|
Ip_bool remote_transport_udp_encapsulate;
|
|
Ip_bool remote_mh_udp_encapsulate;
|
|
|
|
struct Ip_in6_addr nexthop;
|
|
Ip_u32 ifindex;
|
|
} tun;
|
|
|
|
struct Ipmip6_mib_mip6NodeTrafficEntry mip6NodeTrafficEntry;
|
|
struct
|
|
{
|
|
struct Ip_timeval basetick;
|
|
struct Ip_timeval basetime;
|
|
struct Ip_timeval current;
|
|
} stats;
|
|
} Ipmip6mn_route_tunnel_t;
|
|
|
|
|
|
typedef void (*Ipmip6mn_route_func_t) (struct Ipmip6mn_context *ctx, struct Ipmip_proc *proc, int cmd, Ipmip6mn_route_tunnel_t *rtifp);
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC void ipmip6mn_route_address(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_address_inet(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_blackhole_ipv6(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_blackhole_ipv4(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_transport_ha_ipv6_using_ipv6(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_transport_ha_MH_using_udp_encap(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
|
|
IP_STATIC void ipmip6mn_route_transport_ha_MH_home(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
|
|
IP_STATIC void ipmip6mn_route_transport_ipv6_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_transport_ipv4_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_transport_nemov6_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
IP_STATIC void ipmip6mn_route_transport_nemov4_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
static const char *route_types[IPMIP6MN_ROUTE_TYPE_MAX] =
|
|
{
|
|
"none",
|
|
"blackhole",
|
|
"home agent",
|
|
"tunnel",
|
|
"home",
|
|
"home pending"
|
|
};
|
|
|
|
static Ipmip6mn_route_func_t ipmip6mn_route_funcs[IPMIP6MN_ROUTE_BIT_MAX] =
|
|
{
|
|
ipmip6mn_route_address,
|
|
ipmip6mn_route_address_inet,
|
|
ipmip6mn_route_blackhole_ipv6,
|
|
ipmip6mn_route_blackhole_ipv4,
|
|
ipmip6mn_route_transport_ha_ipv6_using_ipv6,
|
|
ipmip6mn_route_transport_ha_MH_using_udp_encap,
|
|
ipmip6mn_route_transport_ha_MH_home,
|
|
ipmip6mn_route_transport_ipv6_using_ipvX,
|
|
ipmip6mn_route_transport_ipv4_using_ipvX,
|
|
ipmip6mn_route_transport_nemov6_using_ipvX,
|
|
ipmip6mn_route_transport_nemov4_using_ipvX
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_STATIC int
|
|
ipmip6mn_route_policy(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ip_u8 family,
|
|
Ip_u32 prio,
|
|
int cmd,
|
|
Ip_u32 ifindex,
|
|
const void *saddr,
|
|
Ip_u32 saddr_len,
|
|
const void *daddr,
|
|
Ip_u32 daddr_len,
|
|
Ip_u32 table,
|
|
Ip_u32 extact)
|
|
{
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"ip rule %s from %s/%d to %s/%d%s%s prio %u table %d",
|
|
cmd == IP_RTM_NEWRULE? "add" : "delete",
|
|
ipmip_ntop(proc, family, saddr? saddr : &ip_in6addr_any, IP_NULL),
|
|
saddr_len,
|
|
ipmip_ntop(proc, family, daddr? daddr : &ip_in6addr_any, IP_NULL),
|
|
daddr_len,
|
|
ifindex? " dev " : "",
|
|
ifindex? ipcom_if_indextoname(ifindex, proc->ntop.ntop_name) : "",
|
|
prio,
|
|
table));
|
|
|
|
return ipmip_netlink_inX_rule(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
family,
|
|
cmd,
|
|
table,
|
|
prio,
|
|
ifindex,
|
|
saddr? saddr : &ip_in6addr_any,
|
|
(Ip_u8)(saddr? saddr_len : 0),
|
|
daddr? daddr : &ip_in6addr_any,
|
|
(Ip_u8)(daddr? daddr_len : 0),
|
|
0,
|
|
extact);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_tunnel_cleanup(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_route_tunnel_t *ife)
|
|
{
|
|
/* Move routing state to NONE */
|
|
ipmip6mn_route_change(ctx, proc, &ife->iff6, IPMIP6MN_ROUTE_TYPE_NONE);
|
|
|
|
/* Delete the route tables */
|
|
ipmip_util_route_table_free(&ctx->ipmip6.ipmip, proc, ife->rtable);
|
|
ipmip_util_route_table_free(&ctx->ipmip6.ipmip, proc, ife->btable);
|
|
ipmip_util_route_table_free(&ctx->ipmip6.ipmip, proc, ife->htable);
|
|
ipmip_util_route_table_free(&ctx->ipmip6.ipmip, proc, ife->nemo_table);
|
|
ipmip_util_route_table_free(&ctx->ipmip6.ipmip, proc, ife->nemo_stats);
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_address(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
/* Setup the inbound statistics route */
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
/* Time to create a route for this prefix. */
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_RX,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->inet6,
|
|
sizeof(rtifp->inet6),
|
|
128,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_RECV,
|
|
IP_NULL,
|
|
IPNET_RTF_SKIP);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
0);
|
|
break;
|
|
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_stats,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
IP_RTN_THROW);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_address_inet(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
#ifdef IPMIP_USE_INET
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
/* Setup the inbound statistics route */
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
if (rtifp->inet != 0)
|
|
{
|
|
/* Time to create a route for this prefix. */
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_RX,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->inet,
|
|
sizeof(rtifp->inet),
|
|
32,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_RECV,
|
|
IP_NULL,
|
|
IPNET_RTF_SKIP);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
0);
|
|
}
|
|
break;
|
|
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
if (rtifp->inet != 0)
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
0);
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_stats,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
IP_RTN_THROW);
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(cmd);
|
|
IPMIP_UNUSED_PARAMETER(rtifp);
|
|
#endif
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_blackhole_ipv6(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
cmd == IPMIP6MN_ROUTE_DO_ADD? IP_RTM_NEWRULE : IP_RTM_DELRULE,
|
|
0,
|
|
&rtifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->btable,
|
|
0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_blackhole_ipv4(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
#ifdef IPMIP_USE_INET
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
cmd == IPMIP6MN_ROUTE_DO_ADD? IP_RTM_NEWRULE : IP_RTM_DELRULE,
|
|
0,
|
|
&rtifp->inet,
|
|
32,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->btable,
|
|
0);
|
|
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(cmd);
|
|
IPMIP_UNUSED_PARAMETER(rtifp);
|
|
#endif
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_ha_ipv6_using_ipv6(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, IP_RTM_NEWMIP, 0);
|
|
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
|
|
|
|
msg->mip_family = IP_AF_INET6;
|
|
msg->mip_type = IP_WRMOB6_NEW_ROUTE_RO_DSTOPT;
|
|
msg->mip_flags = 0;
|
|
|
|
/* Create the nested HoA attribute */
|
|
hdr_off = ipmip_netlink_nlmsghdr_rta_begin(&rbuf, IP_MIP_ENCAP);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_IFINDEX, rtifp->tun.ifindex);
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_DST, sizeof(struct Ip_in6_addr), &rtifp->tun.remote_inet6);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_DST_LEN, 128);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_TABLE, rtifp->rtable);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_FLAGS, IPNET_RTF_GATEWAY);
|
|
|
|
ipmip_netlink_nlmsghdr_rta_put_in6(&rbuf, IP_WRMOB6_ROUTE_HOA, &rtifp->inet6);
|
|
ipmip_netlink_nlmsghdr_rta_put_in6(&rbuf, IP_WRMOB6_ROUTE_COA, &rtifp->tun.local.in6);
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_GW, sizeof(rtifp->tun.nexthop), &rtifp->tun.nexthop);
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_HANDLE, sizeof(handle), &handle);
|
|
|
|
ipmip_netlink_nlmsghdr_rta_end(&rbuf, hdr_off);
|
|
|
|
/* Complete the buffer */
|
|
ipmip_netlink_nlmsghdr_done(&rbuf, 0);
|
|
|
|
/* NETLINK request */
|
|
ret = ipmip_netlink_request(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
ctx->ipmip6.ipmip.nl_req,
|
|
0,
|
|
0,
|
|
(struct Ip_nlmsghdr *)IPMIP_BUFFER_PTR(&rbuf),
|
|
IP_NULL);
|
|
/**/
|
|
ipmip_buffer_release(&rbuf);
|
|
|
|
if (ret < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"Unable to perform MIP6 command NEWMIP/DSTOPT = %d", -ret));
|
|
}
|
|
}
|
|
|
|
/* Nexthop routing */
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->btable,
|
|
0);
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_NEWROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->rtable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->btable,
|
|
0);
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_ha_MH_using_udp_encap(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
0,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
sizeof(struct Ip_in6_addr),
|
|
128,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp),
|
|
IPMIP6MN_ROUTE_ENDPOINT_PORT(rtifp, IP_TRUE),
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_SEND,
|
|
IP_NULL,
|
|
IPNET_RTF_MBINDING|IPNET_RTF_TUNNELEND);
|
|
|
|
if (rtifp->tun.family != IP_AF_INET6)
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPCOM_ROUTE_TABLE_DEFAULT,
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_NEWROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
}
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->btable,
|
|
0);
|
|
|
|
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
if (rtifp->tun.family != IP_AF_INET6)
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPCOM_ROUTE_TABLE_DEFAULT,
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
}
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
rtifp->tun.family,
|
|
IPMIP6MN_ROUTE_BLACKHOLE,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->btable,
|
|
0);
|
|
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
break;
|
|
}
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_ha_MH_home(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_NEWROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->htable,
|
|
rtifp->tun.ifindex,
|
|
&rtifp->tun.remote_inet6,
|
|
128,
|
|
&rtifp->tun.nexthop,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_COA,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
IPMIP6MN_ROUTE_LOCAL(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp) * 8,
|
|
rtifp->htable,
|
|
0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipmn_route_blackhole
|
|
*===========================================================================
|
|
* Description: Add/delete blackhole route "0.0.0.0/0 -> 127.0.0.1"
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_nemov6_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
Ipmip6mn_entry_nemo_t *nemo;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
/* Go through the NEMO tables */
|
|
for (nemo = IPCOM_LIST_FIRST(&rtifp->node->config->nemo); nemo != IP_NULL; nemo = IPCOM_LIST_NEXT(&nemo->nemo_next))
|
|
{
|
|
if ((nemo->nemo_ifindex = ipcom_if_nametoindex(nemo->nemo_ingress)) != 0)
|
|
{
|
|
unsigned i;
|
|
|
|
nemo->nemo_installed = IP_TRUE;
|
|
|
|
ipmip6mn_route_policy(ctx, proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
nemo->nemo_ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_table,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
|
|
for (i = 0; i < nemo->nemo_prefixes.numelem; i++)
|
|
{
|
|
Ipmip6_mh_mo_mobile_prefix_t *mo = (Ipmip6_mh_mo_mobile_prefix_t *)nemo->nemo_prefixes.hdrs[i];
|
|
|
|
/* Time to create a route for this prefix. */
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
0,
|
|
rtifp->nemo_table,
|
|
rtifp->iff6.iff.ifindex,
|
|
&mo->prefix,
|
|
sizeof(mo->prefix),
|
|
mo->prefix_length,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp),
|
|
IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(rtifp),
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_SEND,
|
|
IP_NULL,
|
|
IPNET_RTF_MBINDING|IPNET_RTF_TUNNELEND);
|
|
|
|
/* Time to create a route for this prefix. */
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
nemo->nemo_ifindex,
|
|
&mo->prefix,
|
|
sizeof(mo->prefix),
|
|
mo->prefix_length,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_RECV,
|
|
IP_NULL,
|
|
IPNET_RTF_SKIP);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
/* Go through the NEMO tables */
|
|
for (nemo = IPCOM_LIST_FIRST(&rtifp->node->config->nemo); nemo != IP_NULL; nemo = IPCOM_LIST_NEXT(&nemo->nemo_next))
|
|
{
|
|
if (nemo->nemo_installed)
|
|
{
|
|
unsigned i;
|
|
ipmip6mn_route_policy(ctx, proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
nemo->nemo_ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_table,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
for (i = 0; i < nemo->nemo_prefixes.numelem; i++)
|
|
{
|
|
Ipmip6_mh_mo_mobile_prefix_t *mo = (Ipmip6_mh_mo_mobile_prefix_t *)nemo->nemo_prefixes.hdrs[i];
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_table,
|
|
rtifp->iff6.iff.ifindex,
|
|
&mo->prefix,
|
|
mo->prefix_length,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_stats,
|
|
nemo->nemo_ifindex,
|
|
&mo->prefix,
|
|
mo->prefix_length,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
}
|
|
|
|
nemo->nemo_installed = IP_FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmipmn_route_blackhole
|
|
*===========================================================================
|
|
* Description: Add/delete blackhole route "0.0.0.0/0 -> 127.0.0.1"
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_nemov4_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
#ifdef IPMIP_USE_INET
|
|
Ipmip6mn_dsmipv6_nemo_t *nemo;
|
|
Ipmip6mn_dsmipv6_nemo_prefix_t *nw;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
/* Go through the NEMO tables */
|
|
for (nemo = IPCOM_LIST_FIRST(&rtifp->node->config->dsmipv6.nemo); nemo != IP_NULL; nemo = IPCOM_LIST_NEXT(&nemo->nemo_next))
|
|
{
|
|
if ((nemo->nemo_if.ifindex = ipcom_if_nametoindex(nemo->nemo_if.ifname)) != 0)
|
|
{
|
|
ipmip_if_resolve_lla(&ctx->ipmip6.ipmip, proc, &nemo->nemo_if);
|
|
ipmip6mn_route_policy(ctx, proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
nemo->nemo_if.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_table,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
|
|
for (nw = nemo->nemo_dsmipv6; nw != IP_NULL; nw = nw->next_nemo_prefix)
|
|
{
|
|
if (nw->request_prefix && nw->updated == IP_TRUE && nw->status == IPMIP6_MH_BU_DSMIPV6_HOA_ACK_SUCCESS)
|
|
{
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
0,
|
|
rtifp->nemo_table,
|
|
rtifp->iff6.iff.ifindex,
|
|
&nw->runtime_prefix,
|
|
sizeof(nw->runtime_prefix),
|
|
nw->runtime_prefix_length,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp),
|
|
IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(rtifp),
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_SEND,
|
|
IP_NULL,
|
|
IPNET_RTF_MBINDING|IPNET_RTF_TUNNELEND);
|
|
|
|
/* Time to create a route for this prefix. */
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
0,
|
|
rtifp->nemo_stats,
|
|
nemo->nemo_if.ifindex,
|
|
&nw->runtime_prefix,
|
|
sizeof(nw->runtime_prefix),
|
|
nw->runtime_prefix_length,
|
|
IP_NULL,
|
|
0,
|
|
0,
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_RECV,
|
|
IP_NULL,
|
|
IPNET_RTF_SKIP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
/* Go through the NEMO tables */
|
|
for (nemo = IPCOM_LIST_FIRST(&rtifp->node->config->dsmipv6.nemo); nemo != IP_NULL; nemo = IPCOM_LIST_NEXT(&nemo->nemo_next))
|
|
{
|
|
if (nemo->nemo_if.ifindex != 0)
|
|
{
|
|
ipmip6mn_route_policy(ctx, proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
nemo->nemo_if.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->nemo_table,
|
|
IP_FIB_RULE_FIND_SADDR);
|
|
|
|
for (nw = nemo->nemo_dsmipv6; nw != IP_NULL; nw = nw->next_nemo_prefix)
|
|
{
|
|
if (nw->request_prefix && nw->updated == IP_TRUE && nw->status == IPMIP6_MH_BU_DSMIPV6_HOA_ACK_SUCCESS)
|
|
{
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_table,
|
|
rtifp->iff6.iff.ifindex,
|
|
&nw->runtime_prefix,
|
|
nw->runtime_prefix_length,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->nemo_stats,
|
|
nemo->nemo_if.ifindex,
|
|
&nw->runtime_prefix,
|
|
nw->runtime_prefix_length,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(cmd);
|
|
IPMIP_UNUSED_PARAMETER(rtifp);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_tunnel
|
|
*===========================================================================
|
|
* Description: Add/delete blackhole route "0.0.0.0/0 -> 127.0.0.1"
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_ipv6_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
IP_WRMOB6_NEW_TYPE_SILENT,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
&ip_in6addr_any,
|
|
sizeof(ip_in6addr_any),
|
|
0,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp),
|
|
IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(rtifp),
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_SEND,
|
|
IP_NULL,
|
|
IPNET_RTF_MBINDING|IPNET_RTF_TUNNELEND);
|
|
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
/* Delete the tunneling route */
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_tunnel
|
|
*===========================================================================
|
|
* Description: Add/delete blackhole route "0.0.0.0/0 -> 127.0.0.1"
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6mn_route_transport_ipv4_using_ipvX(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
#ifdef IPMIP_USE_INET
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = rtifp->node->identifier;
|
|
|
|
switch (cmd)
|
|
{
|
|
case IPMIP6MN_ROUTE_DO_ADD:
|
|
ipmip6_netlink_route_mip_do(&ctx->ipmip6,
|
|
proc,
|
|
IP_RTM_NEWMIP,
|
|
IP_WRMOB6_NEW_LINK_TX,
|
|
IP_WRMOB6_NEW_TYPE_SILENT,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
&ip_inaddr_any,
|
|
sizeof(ip_inaddr_any),
|
|
0,
|
|
IPMIP6MN_ROUTE_ENDPOINT(rtifp),
|
|
IPMIP6MN_ROUTE_SIZE(rtifp),
|
|
IPMIP6MN_ROUTE_ENDPOINT_PORT_CHECK(rtifp),
|
|
IP_NULL,
|
|
&handle,
|
|
IPMIP_LINK_SEND,
|
|
IP_NULL,
|
|
IPNET_RTF_MBINDING|IPNET_RTF_TUNNELEND);
|
|
break;
|
|
case IPMIP6MN_ROUTE_DO_DEL:
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELROUTE,
|
|
rtifp->rtable,
|
|
rtifp->iff6.iff.ifindex,
|
|
IP_NULL,
|
|
0,
|
|
IP_NULL,
|
|
IP_RTN_UNICAST);
|
|
break;
|
|
}
|
|
#else
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(cmd);
|
|
IPMIP_UNUSED_PARAMETER(rtifp);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_tunnel
|
|
*===========================================================================
|
|
* Description: Add/delete blackhole route "0.0.0.0/0 -> 127.0.0.1"
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6mn_route_statistics_get(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_route_tunnel_t *rtifp)
|
|
{
|
|
ipmip6mn_netlink_get_handle_stat(ctx, proc, rtifp->node);
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_port_tunnel_configure
|
|
*===========================================================================
|
|
* Description: Configure end-points in a tunneling interface.
|
|
* Parameters: ifp - The tunneling interface.
|
|
* local - Local end-point.
|
|
* remote - Remote end-point.
|
|
* router - Route by.
|
|
* Returns: IP_TRUE if successful
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6mn_route_remote_setup(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node,
|
|
struct Ip_in6_addr *remote,
|
|
Ip_u32 inet)
|
|
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
|
|
/**/
|
|
if (inet)
|
|
{
|
|
#ifdef IPMIP_USE_INET
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s remote INET endpoint %s assigned",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipmip_ntop_inet(proc, inet)));
|
|
#endif
|
|
rtifp->tun.remote_inet = inet;
|
|
}
|
|
|
|
/**/
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s remote INET6 endpoint %s assigned",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipmip_ntop_inet6(proc, remote, IP_NULL)));
|
|
|
|
ipcom_memcpy(&rtifp->tun.remote_inet6, remote, sizeof(struct Ip_in6_addr));
|
|
|
|
return ipmip6mn_route_tunnel_configure(ctx, proc, node);
|
|
}
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_remote_transport_udp_encapsulation(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node,
|
|
Ip_bool enable)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s remote TRANSPORT UDP ENCAPSULATION %s",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
enable? "enabled" : "disabled"));
|
|
rtifp->tun.remote_transport_udp_encapsulate = enable;
|
|
|
|
#if 0
|
|
return ipmip6mn_route_tunnel_configure(ctx, proc, node);
|
|
#endif
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_remote_mh_transport_udp_encapsulation(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node,
|
|
Ip_bool enable)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s remote UDP ENCAPSULATION %s",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
enable? "enabled" : "disabled"));
|
|
rtifp->tun.remote_mh_udp_encapsulate = enable;
|
|
rtifp->tun.remote_transport_udp_encapsulate = enable;
|
|
|
|
#if 0
|
|
return ipmip6mn_route_tunnel_configure(ctx, proc, node);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_tunnel_local_setup
|
|
*===========================================================================
|
|
* Description: Configure end-points in a tunneling interface.
|
|
* Parameters: ifp - The tunneling interface.
|
|
* local - Local end-point.
|
|
* remote - Remote end-point.
|
|
* router - Route by.
|
|
* Returns: IP_TRUE if successful
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6mn_route_tunnel_local_setup(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node,
|
|
Ip_u8 family,
|
|
const void *local,
|
|
const struct Ip_in6_addr *nexthop,
|
|
Ip_u32 ifindex)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
|
|
/**/
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
if (rtifp->tun.family == IP_AF_INET6)
|
|
{
|
|
if (!IP_IN6_IS_ADDR_UNSPECIFIED(&rtifp->tun.local.in6) && !IP_IN6_ARE_ADDR_EQUAL(&rtifp->tun.local.in6, &rtifp->inet6))
|
|
{
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_DELADDR,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.local.in6,
|
|
128,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
#ifdef IPMIP_USE_INET
|
|
else if (rtifp->tun.family == IP_AF_INET)
|
|
{
|
|
if (rtifp->tun.local.in.s_addr != 0 && rtifp->tun.local.in.s_addr != rtifp->inet)
|
|
{
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_DELADDR,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.local.in.s_addr,
|
|
32,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (family == IP_AF_INET6)
|
|
{
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s local INET6 endpoint %s set",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipmip_ntop_inet6(proc, (void *)local, IP_NULL)));
|
|
|
|
ipcom_memcpy(&rtifp->tun.local, local, sizeof(struct Ip_in6_addr));
|
|
ipcom_memcpy(&rtifp->tun.nexthop, nexthop, sizeof(*nexthop));
|
|
|
|
if (!IP_IN6_IS_ADDR_UNSPECIFIED(&rtifp->tun.local.in6) && !IP_IN6_ARE_ADDR_EQUAL(&rtifp->tun.local.in6, &rtifp->inet6))
|
|
{
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_NEWADDR,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.local.in6,
|
|
128,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
}
|
|
#ifdef IPMIP_USE_INET
|
|
else if (family == IP_AF_INET)
|
|
{
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s local INET endpoint %s set",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipmip_ntop_inet(proc, IP_GET_32ON8(local))));
|
|
|
|
ipcom_memcpy(&rtifp->tun.local, local, sizeof(struct Ip_in_addr));
|
|
|
|
if (rtifp->tun.local.in.s_addr != 0 && rtifp->tun.local.in.s_addr != rtifp->inet)
|
|
{
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_NEWADDR,
|
|
rtifp->iff6.iff.ifindex,
|
|
&rtifp->tun.local.in.s_addr,
|
|
32,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
rtifp->tun.family = family;
|
|
rtifp->tun.ifindex = ifindex;
|
|
|
|
return ipmip6mn_route_tunnel_configure(ctx, proc, node);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_port_tunnel_configure
|
|
*===========================================================================
|
|
* Description: Configure end-points in a tunneling interface.
|
|
* Parameters: ifp - The tunneling interface.
|
|
* local - Local end-point.
|
|
* remote - Remote end-point.
|
|
* router - Route by.
|
|
* Returns: IP_TRUE if successful
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6mn_route_tunnel_configure(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
struct Ip_ip_tunnel_param tun;
|
|
|
|
/* Change tunnel */
|
|
ipcom_memset(&tun, 0, sizeof(tun));
|
|
ipcom_strncpy(tun.ifr_name, rtifp->iff6.iff.ifname, sizeof(tun.ifr_name));
|
|
|
|
/* Set values */
|
|
if (rtifp->tun.family == IP_AF_INET6)
|
|
{
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s configured with INET6 endpoints",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname));
|
|
|
|
|
|
tun.local_addr.sin6.sin6_family = IP_AF_INET6;
|
|
ipcom_memcpy(&tun.local_addr.sin6.sin6_addr, &rtifp->tun.local.in6, sizeof(struct Ip_in6_addr));
|
|
IPCOM_SA_LEN_SET(&tun.local_addr.sin6, sizeof(struct Ip_sockaddr_in6));
|
|
tun.local_addr.sin6.sin6_port = ctx->ipmip6.pkt->s_udp_nat.sin6_port;
|
|
|
|
tun.remote_addr.sin6.sin6_family = IP_AF_INET6;
|
|
}
|
|
#ifdef IPMIP_USE_INET
|
|
else if (rtifp->tun.family == IP_AF_INET)
|
|
{
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s configured with INET endpoints",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname));
|
|
|
|
tun.local_addr.sin.sin_family = IP_AF_INET;
|
|
ipcom_memcpy(&tun.local_addr.sin.sin_addr, &rtifp->tun.local.in, sizeof(struct Ip_in_addr));
|
|
IPCOM_SA_LEN_SET(&tun.local_addr.sin, sizeof(struct Ip_sockaddr_in))
|
|
|
|
/* Prepare UDP NAT-T */;
|
|
tun.local_addr.sin.sin_port = ctx->ipmip6.pkt->s_udp_nat.sin6_port;
|
|
tun.remote_addr.sin.sin_family = IP_AF_INET;
|
|
}
|
|
#endif
|
|
tun.ttl = 64;
|
|
|
|
|
|
/* Try set the tunnel values */
|
|
if (ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCCHGTUNNEL, &tun) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s ipcom_socketioctl(%s, IP_SIOCCHGTUNNEL) failed: errno = %d)",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipcom_errno));
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/* OK */
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_tunnel_create
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipmip6_if_t *
|
|
ipmip6mn_route_tunnel_create(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ipmip6mn_node_t *node)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *ifp = IP_NULL;
|
|
char gifname[IP_IFNAMSIZ];
|
|
struct Ip_ip_tunnel_param tun;
|
|
int ret;
|
|
#ifdef IPMIP_USE_INET
|
|
Ip_u32 loopback = ip_htonl(IP_INADDR_LOOPBACK);
|
|
#endif
|
|
|
|
|
|
ipcom_snprintf(gifname, sizeof(gifname), "gif%s0", node->name);
|
|
if (ipcom_if_nametoindex(gifname) != 0)
|
|
return IP_NULL;
|
|
|
|
|
|
ifp = (Ipmip6mn_route_tunnel_t *)ipmip6_if_alloc_tunnel(&ctx->ipmip6,
|
|
proc,
|
|
sizeof(*ifp),
|
|
gifname,
|
|
0,
|
|
IPMIP_TUNNELTYPE_IP6IP6,
|
|
IP_FALSE,
|
|
(Ipmip_if_cleanup_t)ipmip6mn_route_tunnel_cleanup);
|
|
if (ifp == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
/**/
|
|
ipcom_memcpy(&ifp->inet6, &node->config->inet6.prefix, sizeof(struct Ip_in6_addr));
|
|
|
|
/**/
|
|
IPMIP6_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s %s created",
|
|
node->name,
|
|
gifname));
|
|
|
|
/* Assign the home address */
|
|
if (ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_NEWADDR, ifp->iff6.iff.ifindex, &ifp->inet6, 128, IP_IFA_F_HOMEADDRESS, 0) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s ipcom_socketioctl(IP_SIOCADDROUTETAB) failed, errno = %d",
|
|
node->name,
|
|
ipcom_errno));
|
|
goto fail;
|
|
}
|
|
|
|
/* Create the MIPv6 policy routing table */
|
|
ifp->rtable = ipmip_util_route_table_alloc(&ctx->ipmip6.ipmip, proc);
|
|
ifp->btable = ipmip_util_route_table_alloc(&ctx->ipmip6.ipmip, proc);
|
|
ifp->htable = ipmip_util_route_table_alloc(&ctx->ipmip6.ipmip, proc);
|
|
ifp->nemo_table = ipmip_util_route_table_alloc(&ctx->ipmip6.ipmip, proc);
|
|
ifp->nemo_stats = ipmip_util_route_table_alloc(&ctx->ipmip6.ipmip, proc);
|
|
|
|
IPMIP6_EVENT_IF(DEBUG2, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s TABLES: %d %d %d",
|
|
node->name, ifp->rtable, ifp->btable, ifp->htable));
|
|
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IP_RTM_NEWROUTE,
|
|
ifp->btable,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
&ip_in6addr_loopback,
|
|
IP_RTN_BLACKHOLE);
|
|
#ifdef IPMIP_USE_INET
|
|
ipmip_netlink_inX_route(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
IP_AF_INET,
|
|
IP_RTM_NEWROUTE,
|
|
ifp->btable,
|
|
0,
|
|
IP_NULL,
|
|
0,
|
|
&loopback,
|
|
IP_RTN_BLACKHOLE);
|
|
#endif
|
|
|
|
|
|
if ((ret = ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
&ifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
0,
|
|
ifp->rtable,
|
|
0)) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s POLICY: %d",
|
|
node->name, -ret));
|
|
}
|
|
|
|
/* Change tunnel */
|
|
ipcom_memset(&tun, 0, sizeof(tun));
|
|
ipcom_strncpy(tun.ifr_name, ifp->iff6.iff.ifname, sizeof(tun.ifr_name));
|
|
|
|
/* Set values */
|
|
tun.local_addr.sin6.sin6_family = IP_AF_INET6;
|
|
tun.local_addr.sin6.sin6_addr = ip_in6addr_any;
|
|
IPCOM_SA_LEN_SET(&tun.local_addr.sin6, sizeof(struct Ip_sockaddr_in6));
|
|
tun.remote_addr.sin6.sin6_family = IP_AF_INET6;
|
|
tun.remote_addr.sin6.sin6_addr = ip_in6addr_any;
|
|
IPCOM_SA_LEN_SET(&tun.remote_addr.sin6, sizeof(struct Ip_sockaddr_in6));
|
|
tun.remote_addr.sin6.sin6_scope_id = 3;
|
|
tun.ttl = 64;
|
|
|
|
/* Try set the tunnel values */
|
|
if (ipmip_util_ioctl(&ctx->ipmip6.ipmip, proc, IP_SIOCCHGTUNNEL, &tun) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s ipcom_socketioctl(%s, IP_SIOCCHGTUNNEL) failed: errno = %d",
|
|
node->name,
|
|
gifname,
|
|
ipcom_errno));
|
|
goto fail;
|
|
}
|
|
|
|
ifp->node = node;
|
|
|
|
/**/
|
|
return &ifp->iff6;
|
|
|
|
fail:
|
|
ipmip_if_free(&ctx->ipmip6.ipmip, proc, &ifp->iff6.iff);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_change
|
|
*===========================================================================
|
|
* Description: Upgrade the route to a more explicit route type.
|
|
* Parameters: data - The context
|
|
* proc - The process
|
|
* rtn - Route information
|
|
* type - Type of route.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmip6mn_route_change(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ipmip6_if *ifp,
|
|
int type)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
int otype = rtifp->route_type;
|
|
int ostate = rtifp->route_state;
|
|
int state = 0;
|
|
int dstate = 0;
|
|
int i;
|
|
int rs_home_agent = IPMIP6MN_ROUTE_STATE_HOME_AGENT|IPMIP6MN_ROUTE_STATE_ADDRESS;
|
|
int rs_home_pending= IPMIP6MN_ROUTE_STATE_HOME_AGENT_HOME;
|
|
int rs_blackhole = IPMIP6MN_ROUTE_STATE_BLACKHOLE;
|
|
int rs_tunnel = IPMIP6MN_ROUTE_STATE_TUNNEL|IPMIP6MN_ROUTE_STATE_ADDRESS;
|
|
int rs_address = IPMIP6MN_ROUTE_STATE_TUNNEL;
|
|
int rs_nemo = IPMIP6MN_ROUTE_STATE_NEMO;
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
if (rtifp->inet)
|
|
{
|
|
/* We have an inet state; do update with dsmipv6 */
|
|
rs_home_agent |= IPMIP6MN_ROUTE_STATE_ADDRESS_INET;
|
|
rs_blackhole |= IPMIP6MN_ROUTE_STATE_BLACKHOLE_INET;
|
|
rs_tunnel |= IPMIP6MN_ROUTE_STATE_TUNNEL_INET|IPMIP6MN_ROUTE_STATE_ADDRESS_INET;
|
|
rs_nemo |= IPMIP6MN_ROUTE_STATE_NEMO_INET;
|
|
}
|
|
#endif
|
|
|
|
if (rtifp->tun.family != IP_AF_INET6 || rtifp->tun.remote_transport_udp_encapsulate)
|
|
{
|
|
/* Switch home agent route state */
|
|
rs_home_agent = IPMIP6MN_ROUTE_STATE_HOME_AGENT_UDP;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case IPMIP6MN_ROUTE_TYPE_NONE:
|
|
break;
|
|
case IPMIP6MN_ROUTE_TYPE_BLACKHOLE:
|
|
state = rs_blackhole;
|
|
break;
|
|
case IPMIP6MN_ROUTE_TYPE_HOME_AGENT:
|
|
state = rs_blackhole|rs_home_agent;
|
|
break;
|
|
case IPMIP6MN_ROUTE_TYPE_TUNNEL:
|
|
state = rs_tunnel|rs_home_agent|rs_nemo|rs_address;
|
|
break;
|
|
case IPMIP6MN_ROUTE_TYPE_HOME_PENDING:
|
|
state = rs_home_pending|rs_blackhole;
|
|
break;
|
|
case IPMIP6MN_ROUTE_TYPE_HOME:
|
|
break;
|
|
}
|
|
|
|
if (state == ostate)
|
|
{
|
|
if (type != otype)
|
|
{
|
|
IPMIP6_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s Routing type changed %s(%x) -> %s(%x)",
|
|
rtifp->node->name,
|
|
route_types[otype],
|
|
ostate,
|
|
route_types[type],
|
|
state));
|
|
rtifp->route_type = type;
|
|
}
|
|
return otype;
|
|
}
|
|
|
|
ipmip6mn_route_statistics_get(ctx, proc, rtifp);
|
|
|
|
dstate = state ^ rtifp->route_state;
|
|
|
|
/* Add any new states */
|
|
while ((i = ipcom_ffs((Ip_u32)dstate)) != 0)
|
|
{
|
|
int bitmask = (1 << (i - 1));
|
|
dstate &= ~bitmask;
|
|
if ((state & bitmask) != 0)
|
|
{
|
|
/* The bit's set in the new route state */
|
|
(*ipmip6mn_route_funcs[i - 1])(ctx, proc, IPMIP6MN_ROUTE_DO_ADD, rtifp);
|
|
}
|
|
}
|
|
|
|
dstate = state ^ rtifp->route_state;
|
|
|
|
/* Remove any old states no longer set */
|
|
while ((i = ipcom_ffs((Ip_u32)dstate)) != 0)
|
|
{
|
|
int bitmask = (1 << (i - 1));
|
|
dstate &= ~bitmask;
|
|
if ((rtifp->route_state & bitmask) != 0)
|
|
{
|
|
/* The bit's set in the current route state */
|
|
(*ipmip6mn_route_funcs[i - 1])(ctx, proc, IPMIP6MN_ROUTE_DO_DEL, rtifp);
|
|
}
|
|
}
|
|
|
|
|
|
IPMIP6_EVENT_IF(INFO, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s Routing state changed %s(%x) -> %s(%x)",
|
|
rtifp->node->name,
|
|
route_types[otype],
|
|
ostate,
|
|
route_types[type],
|
|
state));
|
|
rtifp->route_type = type;
|
|
rtifp->route_state = state;
|
|
return otype;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6mn_route_statistics
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_statistics(Ipmip6mn_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ipmip6_if *ifp)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
|
|
ipmip6mn_route_statistics_get(ctx, proc, rtifp);
|
|
}
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_add_outbound(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip6_if *ifp,
|
|
Ip_u64 octets,
|
|
Ip_u64 pkts)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
|
|
IP_U64_ADD(rtifp->mip6NodeTrafficEntry.mip6HCNodeOutOctets, octets);
|
|
rtifp->mip6NodeTrafficEntry.mip6NodeOutOctets = IP_U64_GETLO(rtifp->mip6NodeTrafficEntry.mip6HCNodeOutOctets);
|
|
IP_U64_ADD(rtifp->mip6NodeTrafficEntry.mip6HCNodeOutPkts, pkts);
|
|
rtifp->mip6NodeTrafficEntry.mip6NodeOutPkts = IP_U64_GETLO(rtifp->mip6NodeTrafficEntry.mip6HCNodeOutPkts);
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_add_inbound(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip6_if *ifp,
|
|
Ip_u64 octets,
|
|
Ip_u64 pkts)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
|
|
IP_U64_ADD(rtifp->mip6NodeTrafficEntry.mip6HCNodeInOctets, octets);
|
|
rtifp->mip6NodeTrafficEntry.mip6NodeInOctets = IP_U64_GETLO(rtifp->mip6NodeTrafficEntry.mip6HCNodeInOctets);
|
|
IP_U64_ADD(rtifp->mip6NodeTrafficEntry.mip6HCNodeInPkts, pkts);
|
|
rtifp->mip6NodeTrafficEntry.mip6NodeInPkts = IP_U64_GETLO(rtifp->mip6NodeTrafficEntry.mip6HCNodeInPkts);
|
|
}
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_attr_put(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6_if *ifp,
|
|
Ipmip_buffer_t *msg)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
|
|
/* Put tunnel name */
|
|
ipmip_attr_put_str(msg,
|
|
IPMIP6MN_CLI_NETWORK_ATTR_TUNNEL_IFNAME,
|
|
ifp->iff.ifname);
|
|
|
|
/* Put the registration counter entry */
|
|
ipmip_attr_put(msg,
|
|
IPMIP6MN_CLI_NETWORK_ATTR_MIB_mip6NodeTrafficEntry,
|
|
sizeof(rtifp->mip6NodeTrafficEntry),
|
|
&rtifp->mip6NodeTrafficEntry);
|
|
}
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_binding_attr_put(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6_if *ifp,
|
|
struct Ipmip6_bc *bc,
|
|
Ipmip_buffer_t *msg)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
Ip_u32 encap = IPMIP6MN_CLI_NETWORK_ATTR_ENCAP_IP6IP6;
|
|
const char *ifname;
|
|
|
|
IPMIP_UNUSED_PARAMETER(ctx);
|
|
IPMIP_UNUSED_PARAMETER(proc);
|
|
IPMIP_UNUSED_PARAMETER(bc);
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
if (rtifp->tun.family == IP_AF_INET)
|
|
{
|
|
if (rtifp->tun.remote_transport_udp_encapsulate)
|
|
encap = IPMIP6MN_CLI_NETWORK_ATTR_ENCAP_IPIP_UDP;
|
|
else
|
|
encap = IPMIP6MN_CLI_NETWORK_ATTR_ENCAP_IPIP;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (rtifp->tun.remote_transport_udp_encapsulate)
|
|
encap = IPMIP6MN_CLI_NETWORK_ATTR_ENCAP_IP6IP6_UDP;
|
|
else
|
|
encap = IPMIP6MN_CLI_NETWORK_ATTR_ENCAP_IP6IP6;
|
|
}
|
|
|
|
ifname = ipcom_if_indextoname(rtifp->tun.ifindex, proc->ntop.ntop_name);
|
|
if (ifname)
|
|
ipmip_attr_put_str(msg,
|
|
IPMIP6MN_CLI_NETWORK_ATTR_BINDING_ITEM_IFNAME,
|
|
ifname);
|
|
ipmip_attr_put_u32(msg,
|
|
IPMIP6MN_CLI_NETWORK_ATTR_BINDING_ITEM_ENCAP,
|
|
encap);
|
|
}
|
|
|
|
#ifdef IPMIP_USE_INET
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_dsmipv6_set(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6_if *ifp,
|
|
Ip_u32 addr,
|
|
Ip_u8 plen)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)ifp;
|
|
|
|
if (rtifp->inet != 0 && (addr == 0 || rtifp->inet != addr))
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
&rtifp->inet,
|
|
32,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->rtable,
|
|
0);
|
|
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_DELADDR, rtifp->iff6.iff.ifindex, &rtifp->inet, 32, IP_IFA_F_HOMEADDRESS, 0);
|
|
}
|
|
|
|
if (addr != 0 && addr != rtifp->inet)
|
|
{
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
&addr,
|
|
32,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->rtable,
|
|
0);
|
|
ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip, proc, IP_AF_INET, IP_RTM_NEWADDR, rtifp->iff6.iff.ifindex, &addr, 32, IP_IFA_F_HOMEADDRESS, IP_IFA_F_X_PREFERRED);
|
|
}
|
|
|
|
rtifp->inet = addr;
|
|
rtifp->inet_plen = plen;
|
|
}
|
|
#endif
|
|
|
|
IP_GLOBAL void
|
|
ipmip6mn_route_tunnel_reassign(struct Ipmip6mn_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6mn_node *node,
|
|
struct Ip_in6_addr *hoa)
|
|
{
|
|
Ipmip6mn_route_tunnel_t *rtifp = (Ipmip6mn_route_tunnel_t *)node->persistent.tunnel;
|
|
int rs = ipmip6mn_route_change(ctx, proc, &rtifp->iff6, IPMIP6MN_ROUTE_TYPE_NONE);
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_DELRULE,
|
|
0,
|
|
&rtifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->rtable,
|
|
0);
|
|
|
|
/* Assign the home address */
|
|
if (ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_DELADDR, rtifp->iff6.iff.ifindex, &rtifp->inet6, 128, IP_IFA_F_HOMEADDRESS, 0) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s unable to delete Home Address from %s, errno = %d",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipcom_errno));
|
|
}
|
|
|
|
ipcom_memcpy(&rtifp->inet6, hoa, sizeof(struct Ip_in6_addr));
|
|
|
|
/* Assign the home address */
|
|
if (ipmip_netlink_inX_addr(&ctx->ipmip6.ipmip, proc, IP_AF_INET6, IP_RTM_NEWADDR, rtifp->iff6.iff.ifindex, &rtifp->inet6, 128, IP_IFA_F_HOMEADDRESS, 0) < 0)
|
|
{
|
|
IPMIP6_EVENT_IF(ERR, proc,
|
|
ipmip_log_event_add(&ctx->ipmip6.ipmip,
|
|
proc,
|
|
"%s unable to add Home Address to %s, errno = %d",
|
|
rtifp->node->name,
|
|
rtifp->iff6.iff.ifname,
|
|
ipcom_errno));
|
|
}
|
|
|
|
ipmip6mn_route_policy(ctx,
|
|
proc,
|
|
IP_AF_INET6,
|
|
IPMIP6MN_ROUTE_PRIORITY,
|
|
IP_RTM_NEWRULE,
|
|
0,
|
|
&rtifp->inet6,
|
|
128,
|
|
IP_NULL,
|
|
0,
|
|
rtifp->rtable,
|
|
0);
|
|
|
|
|
|
ipmip6mn_route_change(ctx, proc, &rtifp->iff6, rs);
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipmip6mn_netlink_new_handle(Ipmip6mn_context_t *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6mn_node *node)
|
|
{
|
|
/**/
|
|
return ipmip6_netlink_new_handle(&ctx->ipmip6, proc, IPCOM_IPD_ID_IPMIP6MN, node->identifier);
|
|
}
|
|
|
|
IP_GLOBAL int
|
|
ipmip6mn_netlink_del_handle(Ipmip6mn_context_t *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6mn_node *node)
|
|
{
|
|
/**/
|
|
return ipmip6_netlink_del_handle(&ctx->ipmip6, proc, IPCOM_IPD_ID_IPMIP6MN, node->identifier);
|
|
}
|
|
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6mn_netlink_get_handle_stat(Ipmip6mn_context_t *ctx,
|
|
struct Ipmip_proc *proc,
|
|
struct Ipmip6mn_node *node)
|
|
{
|
|
Ipmip6_netlink_kern_statistics_t link_recv, link_send;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
/* Identity */
|
|
handle.mip_facility = IPCOM_IPD_ID_IPMIP6MN;
|
|
handle.mip_ident = node->identifier;
|
|
|
|
/* 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);
|
|
ipmip6mn_route_add_outbound(ctx, node->persistent.tunnel, 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);
|
|
ipmip6mn_route_add_inbound(ctx, node->persistent.tunnel, link_recv.mip_s_octets, link_recv.mip_s_pkts);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|