Files
m241Neelima/components/ip_net2-6.9/ipmip6mn/src/ipmip6mn_route.c
T
2026-07-30 11:19:44 +05:30

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
****************************************************************************
*/