905 lines
31 KiB
C
905 lines
31 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip6_netlink.c,v $ $Revision: 1.23.10.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipmip6/src/ipmip6_netlink.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 "ipmip6_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_sysctl.h>
|
|
#include <ipcom_netif.h>
|
|
#include <ipcom_strlib.h>
|
|
#include <ipcom_ipd.h>
|
|
|
|
#include <ipnet.h>
|
|
#include <ipnet_ip6.h>
|
|
#include <ipnet_netif.h>
|
|
#include <ipnet_icmp6.h>
|
|
#include <ipnet_cmd.h>
|
|
|
|
#include <ipmip.h>
|
|
|
|
#include <ipmip6_h.h>
|
|
#include <private/ipmip6_context.h>
|
|
#include <private/ipmip6_if.h>
|
|
#include <private/ipmip6_pkt.h>
|
|
#include <private/ipmip6_netlink.h>
|
|
#include <private/ipmip6_util.h>
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_process_newlink
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6_netlink_process_route(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ip_nlmsghdr *hdr)
|
|
{
|
|
struct Ip_rtmsg *rtm;
|
|
struct Ip_rtattr *rtattr[IP_RTA_MAX + 1];
|
|
Ipmip6_if_t *ife = IP_NULL;
|
|
|
|
|
|
rtm = IP_NLMSG_DATA(hdr);
|
|
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_RTA_MAX + 1,
|
|
IP_RTM_RTA(rtm),
|
|
IP_RTM_PAYLOAD(hdr),
|
|
rtattr);
|
|
|
|
if (rtattr[IP_RTA_OIF])
|
|
{
|
|
if ((ife = ipmip6_if_lockbyindex(ctx, proc, IP_GET_32ON8(IP_RTA_DATA(rtattr[IP_RTA_OIF])))) == IP_NULL)
|
|
return;
|
|
}
|
|
|
|
/**/
|
|
if (ife != IP_NULL)
|
|
{
|
|
ife->iff_changes++;
|
|
ipmip6_if_release_iflocked(ctx, proc, ife);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
Ipmip6_if_t *nife;
|
|
if (ife)
|
|
{
|
|
/* Lock the interface; touch the changes counter */
|
|
ipmip_timer_lock_acquire(&ctx->ipmip, proc, ife->iff_lock);
|
|
ife->iff_changes++;
|
|
}
|
|
|
|
/* Acquire next interface */
|
|
ipmip_timer_lock_acquire(&ctx->ipmip, proc, ctx->iff.iflock);
|
|
|
|
nife = (Ipmip6_if_t *)(ife? IPCOM_LIST_NEXT(&ife->iff.next) : IPCOM_LIST_FIRST(&ctx->iff.interfaces));
|
|
|
|
if (nife)
|
|
ipmip6_if_reference_locked(ctx, proc, nife);
|
|
ipmip_timer_lock_release(&ctx->ipmip, proc, ctx->iff.iflock);
|
|
|
|
/* Release this lock; will schedule the update */
|
|
if (ife)
|
|
ipmip6_if_release_iflocked(ctx, proc, ife);
|
|
|
|
/* Do next */
|
|
ife = nife;
|
|
} while (ife != IP_NULL);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_process_newlink
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6_netlink_process_link(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ip_nlmsghdr *hdr)
|
|
{
|
|
struct Ip_ifinfomsg *ifm;
|
|
struct Ip_rtattr *iflattr[IP_IFLA_MAX + 1];
|
|
Ipmip6_if_t *ife = IP_NULL;
|
|
|
|
|
|
ifm = IP_NLMSG_DATA(hdr);
|
|
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_IFLA_MAX + 1,
|
|
IP_IFLA_RTA(ifm),
|
|
IP_IFLA_PAYLOAD(hdr),
|
|
iflattr);
|
|
|
|
if (iflattr[IP_IFLA_IFNAME])
|
|
{
|
|
/**/
|
|
ife = ipmip6_if_lockbyname(ctx, proc, ipmip_ntop_strn(proc, IP_RTA_DATA(iflattr[IP_IFLA_IFNAME]), IP_RTA_PAYLOAD(iflattr[IP_IFLA_IFNAME])));
|
|
}
|
|
else if (ifm->ifi_index != 0)
|
|
{
|
|
ife = ipmip6_if_lockbyindex(ctx, proc, ifm->ifi_index);
|
|
}
|
|
|
|
/**/
|
|
if (ife != IP_NULL)
|
|
{
|
|
/**/
|
|
if (hdr->nlmsg_type == IP_RTM_DELLINK)
|
|
{
|
|
ipmip6_if_link_down_iflocked(ctx, proc, ife);
|
|
}
|
|
else
|
|
{
|
|
if ((ifm->ifi_flags & (IP_IFF_UP|IP_IFF_RUNNING)) == (IP_IFF_UP|IP_IFF_RUNNING))
|
|
{
|
|
ipmip6_if_link_up_iflocked(ctx, proc, ife, ifm->ifi_index);
|
|
}
|
|
else
|
|
ipmip6_if_link_down_iflocked(ctx, proc, ife);
|
|
}
|
|
|
|
ipmip6_if_release_iflocked(ctx, proc, ife);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_process_newlink
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipmip6_netlink_process_addr(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ip_nlmsghdr *hdr)
|
|
{
|
|
struct Ip_ifaddrmsg *ifa;
|
|
struct Ip_rtattr *ifattr[IP_IFA_MAX + 1];
|
|
Ipmip6_if_t *ife;
|
|
|
|
|
|
ifa = IP_NLMSG_DATA(hdr);
|
|
|
|
/**/
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_IFA_MAX + 1,
|
|
IP_IFA_RTA(ifa),
|
|
IP_IFA_PAYLOAD(hdr),
|
|
ifattr);
|
|
|
|
if (ifattr[IP_IFA_LOCAL])
|
|
{
|
|
ife = ipmip6_if_lockbyindex(ctx, proc, ifa->ifa_index);
|
|
|
|
/**/
|
|
if (ife != IP_NULL)
|
|
{
|
|
/**/
|
|
if (hdr->nlmsg_type == IP_RTM_DELADDR)
|
|
{
|
|
/**/
|
|
if (ifa->ifa_family == IP_AF_INET6)
|
|
{
|
|
ipmip6_if_inet6_del_iflocked(ctx,
|
|
proc,
|
|
ife,
|
|
(struct Ip_in6_addr *)IP_RTA_DATA(ifattr[IP_IFA_LOCAL]));
|
|
}
|
|
#ifdef IPMIP_USE_INET
|
|
else if (ifa->ifa_family == IP_AF_INET)
|
|
{
|
|
ipmip6_if_inet_del_iflocked(ctx,
|
|
proc,
|
|
ife,
|
|
IP_GET_32ON8(IP_RTA_DATA(ifattr[IP_IFA_LOCAL])));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
if (ifa->ifa_family == IP_AF_INET6)
|
|
{
|
|
ipmip6_if_inet6_add_iflocked(ctx,
|
|
proc,
|
|
ife,
|
|
(struct Ip_in6_addr *)IP_RTA_DATA(ifattr[IP_IFA_LOCAL]),
|
|
ifa->ifa_prefixlen,
|
|
ifa->ifa_scope,
|
|
ifa->ifa_flags);
|
|
}
|
|
#ifdef IPMIP_USE_INET
|
|
else if (ifa->ifa_family == IP_AF_INET)
|
|
{
|
|
ipmip6_if_inet_add_iflocked(ctx,
|
|
proc,
|
|
ife,
|
|
IP_GET_32ON8(IP_RTA_DATA(ifattr[IP_IFA_LOCAL])));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
ipmip6_if_release_iflocked(ctx, proc, ife);
|
|
}
|
|
}
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipmip6_netlink_prefix_do(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ip_u16 type,
|
|
Ip_u32 ifindex,
|
|
const void *prefix,
|
|
Ip_u32 prefix_length,
|
|
Ipmip_buffer_t *reply)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, cmd, 0);
|
|
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
|
|
|
|
msg->mip_family = IP_AF_INET6;
|
|
msg->mip_type = type;
|
|
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_in6(&rbuf, IP_WRMOB6_PREFIX_PREFIX, prefix);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_PREFIX_IFINDEX, ifindex);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_PREFIX_LENGTH, prefix_length);
|
|
ipmip_netlink_nlmsghdr_rta_end(&rbuf, hdr_off);
|
|
|
|
/* Complete the buffer */
|
|
ipmip_netlink_nlmsghdr_done(&rbuf, 0);
|
|
|
|
/* NETLINK request */
|
|
ret = ipmip_netlink_request(&ctx->ipmip,
|
|
proc,
|
|
ctx->ipmip.nl_req,
|
|
0,
|
|
0,
|
|
(struct Ip_nlmsghdr *)IPMIP_BUFFER_PTR(&rbuf),
|
|
reply);
|
|
/**/
|
|
ipmip_buffer_release(&rbuf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_GLOBAL void
|
|
ipmip6_netlink_process(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
struct Ip_nlmsghdr *hdr)
|
|
{
|
|
switch (hdr->nlmsg_type)
|
|
{
|
|
case IP_RTM_NEWLINK:
|
|
case IP_RTM_DELLINK:
|
|
ipmip6_netlink_process_link(ctx, proc, hdr);
|
|
break;
|
|
case IP_RTM_NEWADDR:
|
|
case IP_RTM_DELADDR:
|
|
ipmip6_netlink_process_addr(ctx, proc, hdr);
|
|
break;
|
|
case IP_RTM_NEWROUTE:
|
|
case IP_RTM_DELROUTE:
|
|
ipmip6_netlink_process_route(ctx, proc, hdr);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipmip6_netlink_route_mip_do(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ip_u16 type,
|
|
Ip_u8 flags,
|
|
Ip_u32 table,
|
|
Ip_u32 ifindex,
|
|
const void *prefix,
|
|
Ip_size_t psize,
|
|
Ip_u32 prefix_len,
|
|
const void *nexthop,
|
|
Ip_size_t nsize,
|
|
Ip_u32 nat_port,
|
|
const Ipmip_netlink_kern_compare_t *srccmp,
|
|
const Ipmip_netlink_kern_handle_t *handle,
|
|
int link,
|
|
Ip_u32 *gre_key,
|
|
Ip_u32 rtf_flags)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, cmd, 0);
|
|
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
|
|
|
|
msg->mip_family = IP_AF_INET6;
|
|
msg->mip_type = type;
|
|
msg->mip_flags = flags;
|
|
|
|
/* 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, ifindex);
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_DST, psize, prefix);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_DST_LEN, prefix_len);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_TABLE, table);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_FLAGS, rtf_flags);
|
|
|
|
if ((nat_port & 0xFFFF) != 0)
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_NAT_PORT, nat_port);
|
|
if (nexthop)
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_GW, nsize, nexthop);
|
|
if (srccmp)
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_SRCMAC, sizeof(*srccmp), srccmp);
|
|
if (handle)
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_HANDLE, sizeof(*handle), handle);
|
|
if (gre_key)
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_GRE_KEY, *gre_key);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_LINK, link);
|
|
ipmip_netlink_nlmsghdr_rta_end(&rbuf, hdr_off);
|
|
|
|
/* Complete the buffer */
|
|
ipmip_netlink_nlmsghdr_done(&rbuf, 0);
|
|
|
|
/* NETLINK request */
|
|
ret = ipmip_netlink_request(&ctx->ipmip,
|
|
proc,
|
|
ctx->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->ipmip,
|
|
proc,
|
|
"Unable to perform MIP6 command %d/%d = %d", cmd, type, -ret));
|
|
}
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_activate_address
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmip6_netlink_route_do(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ip_u16 type,
|
|
Ip_u8 flags,
|
|
Ip_u32 table,
|
|
Ip_u32 ifindex,
|
|
const struct Ip_in6_addr *hoa,
|
|
const struct Ip_in6_addr *coa,
|
|
const void *prefix,
|
|
Ip_size_t psize,
|
|
Ip_u32 prefix_len,
|
|
const void *nexthop,
|
|
Ip_size_t nsize,
|
|
Ip_u32 nat_port,
|
|
const Ipmip_netlink_kern_compare_t *srccmp,
|
|
Ip_u32 *gre_key,
|
|
Ipmip_buffer_t *reply,
|
|
Ip_u32 rtf_flags)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, cmd, 0);
|
|
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
|
|
|
|
msg->mip_family = IP_AF_INET6;
|
|
msg->mip_type = type;
|
|
msg->mip_flags = flags;
|
|
|
|
/* 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, ifindex);
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_DST, psize, prefix);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_DST_LEN, prefix_len);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_TABLE, table);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_FLAGS, rtf_flags);
|
|
|
|
if ((nat_port & 0xFFFF) != 0)
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_NAT_PORT, nat_port);
|
|
if (hoa)
|
|
ipmip_netlink_nlmsghdr_rta_put_in6(&rbuf, IP_WRMOB6_ROUTE_HOA, hoa);
|
|
if (coa)
|
|
ipmip_netlink_nlmsghdr_rta_put_in6(&rbuf, IP_WRMOB6_ROUTE_COA, coa);
|
|
if (nexthop)
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_GW, nsize, nexthop);
|
|
if (srccmp)
|
|
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB6_ROUTE_SRCMAC, sizeof(*srccmp), srccmp);
|
|
if (gre_key)
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_ROUTE_GRE_KEY, *gre_key);
|
|
|
|
ipmip_netlink_nlmsghdr_rta_end(&rbuf, hdr_off);
|
|
|
|
/* Complete the buffer */
|
|
ipmip_netlink_nlmsghdr_done(&rbuf, 0);
|
|
|
|
/* NETLINK request */
|
|
ret = ipmip_netlink_request(&ctx->ipmip,
|
|
proc,
|
|
ctx->ipmip.nl_req,
|
|
0,
|
|
0,
|
|
(struct Ip_nlmsghdr *)IPMIP_BUFFER_PTR(&rbuf),
|
|
reply);
|
|
/**/
|
|
ipmip_buffer_release(&rbuf);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_address_statistics
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipmip6_netlink_address_do(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
int cmd,
|
|
Ip_u16 type,
|
|
Ip_u8 flags,
|
|
Ip_u32 ifindex,
|
|
Ip_u8 family,
|
|
const void *addr,
|
|
Ipmip_buffer_t *reply)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, cmd, 0);
|
|
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
|
|
|
|
msg->mip_family = IP_AF_INET6;
|
|
msg->mip_type = type;
|
|
msg->mip_flags = flags;
|
|
|
|
/* Create the nested HoA attribute */
|
|
hdr_off = ipmip_netlink_nlmsghdr_rta_begin(&rbuf, IP_MIP_ENCAP);
|
|
if (addr)
|
|
ipmip_netlink_nlmsghdr_rta_put_inX(&rbuf, IP_WRMOB6_HOA_ADDRESS, family, addr);
|
|
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB6_HOA_IFINDEX, ifindex);
|
|
ipmip_netlink_nlmsghdr_rta_end(&rbuf, hdr_off);
|
|
|
|
/* Complete the buffer */
|
|
ipmip_netlink_nlmsghdr_done(&rbuf, 0);
|
|
|
|
/* NETLINK request */
|
|
ret = ipmip_netlink_request(&ctx->ipmip,
|
|
proc,
|
|
ctx->ipmip.nl_req,
|
|
0,
|
|
0,
|
|
(struct Ip_nlmsghdr *)IPMIP_BUFFER_PTR(&rbuf),
|
|
reply);
|
|
/**/
|
|
ipmip_buffer_release(&rbuf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipmip6_netlink_address_statistics
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6_netlink_prefix_generate(Ipmip6_context_t *ctx,
|
|
Ipmip_proc_t *proc,
|
|
Ip_u32 ifindex,
|
|
const void *prefix,
|
|
Ip_u32 prefix_length,
|
|
Ipmip6_address_t *reply)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_bool ret = IP_FALSE;
|
|
|
|
if (ifindex == 0)
|
|
return IP_FALSE;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
if (ipmip6_netlink_prefix_do(ctx,
|
|
proc,
|
|
IP_RTM_GETMIP,
|
|
IP_WRMOB6_GET_PREFIX_ADDR,
|
|
ifindex,
|
|
prefix,
|
|
prefix_length,
|
|
&rbuf) == 0)
|
|
{
|
|
struct Ip_nlmsghdr *nlhdr = IPMIP_BUFFER_PTR(&rbuf);
|
|
struct Ip_rtattr *rta = ipmip_netlink_nlmsghdr_rta_find(IP_MIP_RTA(IP_NLMSG_DATA(nlhdr)), IP_MIP_PAYLOAD(nlhdr), IP_MIP_ENCAP);
|
|
|
|
if (rta)
|
|
{
|
|
struct Ip_rtattr *pattr[IP_WRMOB6_PREFIX_MAX + 1];
|
|
|
|
/* parse it */
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_WRMOB6_PREFIX_MAX + 1,
|
|
IP_RTA_DATA(rta),
|
|
IP_RTA_PAYLOAD(rta),
|
|
pattr);
|
|
|
|
if (pattr[IP_WRMOB6_PREFIX_PREFIX] && pattr[IP_WRMOB6_PREFIX_LENGTH])
|
|
{
|
|
ipcom_memcpy(&reply->prefix, IP_RTA_DATA(pattr[IP_WRMOB6_PREFIX_PREFIX]), sizeof(reply->prefix));
|
|
reply->len = (Ip_u8) IP_GET_32ON8(IP_RTA_DATA(pattr[IP_WRMOB6_PREFIX_LENGTH]));
|
|
ret = IP_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
ipmip_buffer_release(&rbuf);
|
|
return ret;
|
|
}
|
|
|
|
|
|
IP_GLOBAL int
|
|
ipmip6_netlink_del_handle(struct Ipmip6_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ip_u32 facility,
|
|
Ip_u32 identity)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, IP_RTM_DELMIP, 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_DEL_HANDLE;
|
|
msg->mip_flags = 0;
|
|
|
|
/* Create the nested HoA attribute */
|
|
hdr_off = ipmip_netlink_nlmsghdr_rta_begin(&rbuf, IP_MIP_ENCAP);
|
|
|
|
/* Identity */
|
|
handle.mip_facility = facility;
|
|
handle.mip_ident = identity;
|
|
|
|
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->ipmip,
|
|
proc,
|
|
ctx->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->ipmip,
|
|
proc,
|
|
"Unable to perform MIP6 DEL HANDLE = %d", -ret));
|
|
}
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_GLOBAL int
|
|
ipmip6_netlink_new_handle(struct Ipmip6_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ip_u32 facility,
|
|
Ip_u32 identity)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
Ipmip_netlink_kern_handle_t handle;
|
|
|
|
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_HANDLE;
|
|
msg->mip_flags = 0;
|
|
|
|
/* Create the nested HoA attribute */
|
|
hdr_off = ipmip_netlink_nlmsghdr_rta_begin(&rbuf, IP_MIP_ENCAP);
|
|
|
|
/* Identity */
|
|
handle.mip_facility = facility;
|
|
handle.mip_ident = identity;
|
|
|
|
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->ipmip,
|
|
proc,
|
|
ctx->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->ipmip,
|
|
proc,
|
|
"Unable to perform MIP6 NEW HANDLE = %d", -ret));
|
|
}
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
IP_GLOBAL Ip_bool
|
|
ipmip6_netlink_get_handle_stat(struct Ipmip6_context *ctx,
|
|
struct Ipmip_proc *proc,
|
|
Ipmip_netlink_kern_handle_t *handle,
|
|
Ipmip6_netlink_kern_statistics_t *link_recv,
|
|
Ipmip6_netlink_kern_statistics_t *link_send)
|
|
{
|
|
Ipmip_buffer_t rbuf;
|
|
Ip_size_t hdr_off;
|
|
struct Ip_mipmsg *msg;
|
|
int ret;
|
|
Ipmip_buffer_t reply;
|
|
|
|
ipmip_buffer_init(&rbuf);
|
|
ipmip_buffer_init(&reply);
|
|
|
|
/* Create NLMSG HDR */
|
|
ipmip_netlink_nlmsghdr_request(&rbuf, 0, 0, IP_RTM_GETMIP, 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_GET_HANDLE_STAT;
|
|
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(&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->ipmip,
|
|
proc,
|
|
ctx->ipmip.nl_req,
|
|
0,
|
|
0,
|
|
(struct Ip_nlmsghdr *)IPMIP_BUFFER_PTR(&rbuf),
|
|
&reply);
|
|
/**/
|
|
ipmip_buffer_release(&rbuf);
|
|
|
|
if (ret >= 0)
|
|
{
|
|
struct Ip_nlmsghdr *nlhdr = IPMIP_BUFFER_PTR(&reply);
|
|
Ip_size_t sz = IPMIP_BUFFER_SIZE(&reply);
|
|
|
|
while (IP_NLMSG_OK(nlhdr, sz))
|
|
{
|
|
if (nlhdr->nlmsg_type == IP_RTM_GETMIP)
|
|
{
|
|
struct Ip_rtattr *rta = IP_MIP_RTA(IP_NLMSG_DATA(nlhdr));
|
|
Ip_size_t rta_sz = IP_MIP_PAYLOAD(nlhdr);
|
|
|
|
while (IP_RTA_OK(rta, rta_sz))
|
|
{
|
|
if (rta->rta_type == IP_MIP_ENCAP)
|
|
{
|
|
/**/
|
|
struct Ip_rtattr *srta[IP_WRMOB6_STATS_MAX + 1];
|
|
|
|
ipmip_netlink_nlmsghdr_rta_parse(IP_WRMOB6_STATS_MAX + 1,
|
|
IP_RTA_DATA(rta),
|
|
IP_RTA_PAYLOAD(rta),
|
|
srta);
|
|
|
|
/* Add statistics */
|
|
ipcom_memcpy(link_recv, IP_RTA_DATA(srta[IP_WRMOB6_STATS_LINK_RECV]), sizeof(*link_recv));
|
|
ipcom_memcpy(link_send, IP_RTA_DATA(srta[IP_WRMOB6_STATS_LINK_SEND]), sizeof(*link_send));
|
|
ipmip_buffer_release(&reply);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
rta = IP_RTA_NEXT(rta, rta_sz);
|
|
}
|
|
}
|
|
|
|
nlhdr = IP_NLMSG_NEXT(nlhdr, sz);
|
|
}
|
|
}
|
|
|
|
ipmip_buffer_release(&reply);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|