Files
2026-07-30 11:19:44 +05:30

430 lines
14 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip4_netlink.c,v $ $Revision: 1.7.10.1 $
* $Source: /home/interpeak/CVSRoot/ipmip4/src/ipmip4_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 "ipmip4_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_clib2.h>
#include <ipcom_err.h>
#include <ipcom_inet.h>
#include <ipcom_ipd.h>
#include <ipcom_list.h>
#include <ipcom_hash.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipmip.h>
#include <private/ipmip_log.h>
#include "ipmip4_h.h"
#include <private/ipmip4_context.h>
#include <private/ipmip4_msgext.h>
#include <private/ipmip4_netlink.h>
#include <private/ipmip4_util.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
IP_GLOBAL Ip_bool
ipmip4_netlink_get_handle_stat(struct Ipmip4_context *ctx,
struct Ipmip_proc *proc,
Ipmip_netlink_kern_handle_t *handle,
Ipmip4_netlink_kern_statistics_t *link_recv,
Ipmip4_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_INET;
msg->mip_type = IP_WRMOB4_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_WRMOB4_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_WRMOB4_STATS_MAX + 1];
ipmip_netlink_nlmsghdr_rta_parse(IP_WRMOB4_STATS_MAX + 1,
IP_RTA_DATA(rta),
IP_RTA_PAYLOAD(rta),
srta);
/* Add statistics */
ipcom_memcpy(link_recv, IP_RTA_DATA(srta[IP_WRMOB4_STATS_LINK_RECV]), sizeof(*link_recv));
ipcom_memcpy(link_send, IP_RTA_DATA(srta[IP_WRMOB4_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;
}
IP_GLOBAL int
ipmip4_netlink_del_handle(struct Ipmip4_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_INET;
msg->mip_type = IP_WRMOB4_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_WRMOB4_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)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->ipmip,
proc,
"Unable to perform MIP4 DEL HANDLE = %d", -ret));
}
return ret;
}
IP_GLOBAL int
ipmip4_netlink_new_handle(struct Ipmip4_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_INET;
msg->mip_type = IP_WRMOB4_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_WRMOB4_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)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->ipmip,
proc,
"Unable to perform MIP4 NEW HANDLE = %d", -ret));
}
return ret;
}
IP_GLOBAL int
ipmip4_netlink_address_do(Ipmip4_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_INET;
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_WRMOB4_HOA_ADDRESS, family, addr);
ipmip_netlink_nlmsghdr_rta_put_u32(&rbuf, IP_WRMOB4_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;
}
IP_GLOBAL int
ipmip4_netlink_route_validate(Ipmip4_context_t *ctx,
Ipmip_proc_t *proc,
Ip_u32 ifindex,
Ip_u32 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, IP_RTM_GETMIP, 0);
msg = ipmip_buffer_offset(&rbuf, ipmip_netlink_nlmsghdr_put(&rbuf, IP_NULL, sizeof(*msg)));
msg->mip_family = IP_AF_INET;
msg->mip_type = IP_WRMOB4_GET_VALIDATE_ROUTE;
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_WRMOB4_ROUTE_IFINDEX, ifindex);
ipmip_netlink_nlmsghdr_rta_put(&rbuf, IP_WRMOB4_ROUTE_DST, 4, &addr);
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)
{
IPMIP4_EVENT_IF(ERR, proc,
ipmip_log_event_add(&ctx->ipmip,
proc,
"Unable to perform MIP4 command VALIDATE = %d", -ret));
}
return ret;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/