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

631 lines
22 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_ctrl.c,v $ $Revision: 1.85.10.6 $
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_ctrl.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $o
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* Functions for IP_PUBLIC int ipnet_ctrl(struct Ipnet_tag *tag) function.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipnet_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_err.h>
#include <ipcom_clib.h>
#include "ipnet_h.h"
#include "ipnet_ctrl.h"
#include "ipnet_cmd.h"
#ifdef IPTCP
#include <iptcp.h>
#endif
#ifdef IPSCTP
#include <ipsctp.h>
#endif
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC int ipnet_ctrl_sock(struct Ipnet_tag *tag);
#ifdef IPCOM_USE_INET6
IP_STATIC int ipnet_ctrl_ip6_nc(struct Ipnet_tag *tag);
IP_STATIC int ipnet_ctrl_ip6_prefix(struct Ipnet_tag *tag);
IP_STATIC int ipnet_ctrl_ip6_router(struct Ipnet_tag *tag);
#endif
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_ctrl_sock
*===========================================================================
* Description: Get state of sockets.
* Parameters: tag - The tag structure fill in.
* Returns: 0 >= success, <0 error code.
*
*/
IP_STATIC int
ipnet_ctrl_sock(struct Ipnet_tag *tag)
{
struct Ipnet_tag_sock_data *sock_tag;
sock_tag = (struct Ipnet_tag_sock_data*) tag;
if (tag->size < sizeof(*sock_tag))
{
tag->size = sizeof(*sock_tag);
return -IP_ERRNO_ENOSPC;
}
if (tag->type == IPNET_CTRL_NEW_ENUM_SOCK_DATA)
sock_tag->fd = 0;
else if (tag->type == IPNET_CTRL_CONT_ENUM_SOCK_DATA)
{
if (sock_tag->fd < 0 || sock_tag->fd >= ipnet_conf_max_sockets)
return -IP_ERRNO_EINVAL;
sock_tag->fd++;
}
else
return -IP_ERRNO_EINVAL;
for (; sock_tag->fd < ipnet_conf_max_sockets; sock_tag->fd++)
{
Ipnet_socket *sock = ipnet->sockets[sock_tag->fd];
if (sock != IP_NULL)
{
sock_tag->pid = sock->ipcom.pid;
sock_tag->domain = sock->ipcom.domain;
sock_tag->type = sock->ipcom.type;
sock_tag->protocol = sock->proto;
sock_tag->vr_index = sock->vr_index;
sock_tag->snd_bytes = ipcom_atomic_get(&sock->snd_bytes);
sock_tag->rcv_bytes = sock->ipcom.rcv_bytes;
#ifdef IPSCTP
/* if not SCTP set it with NULL */
sock_tag->priv_data = IP_NULL;
if (IP_IPPROTO_SCTP == sock->proto)
{
sock_tag->priv_data = ipsctp_get_netstat_info(sock);
if (IP_NULL != sock_tag->priv_data)
return IPNET_CTRL_SUCCESS;
}
#endif /* IPSCTP */
#ifdef IPTCP
if (sock->proto == IP_IPPROTO_TCP)
sock_tag->tcp_state = iptcp_get_state(sock);
#endif /* IPTCP */
sock_tag->saddr.in_addr.sin_port = ip_htons(sock->sport);
sock_tag->daddr.in_addr.sin_port = ip_htons(sock->dport);
sock_tag->saddr.in_addr.sin_family = (Ip_u8) sock->ipcom.domain;
sock_tag->daddr.in_addr.sin_family = (Ip_u8) sock->ipcom.domain;
#ifdef IPCOM_USE_INET
if (sock->ipcom.domain == IP_AF_INET)
{
IPCOM_SA_LEN_SET(&sock_tag->saddr.in_addr, sizeof(sock_tag->saddr.in_addr));
sock_tag->saddr.in_addr.sin_addr.s_addr = sock->ip4->saddr_n;
IPCOM_SA_LEN_SET(&sock_tag->daddr.in_addr, sizeof(sock_tag->daddr.in_addr));
sock_tag->daddr.in_addr.sin_addr.s_addr = sock->ip4->daddr_n;
}
#endif /* IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
if (sock->ipcom.domain == IP_AF_INET6)
{
Ip_u32 scope_id = sock->ip6->iscope_id;
IPCOM_SA_LEN_SET(&sock_tag->saddr.in6_addr, sizeof(sock_tag->saddr.in6_addr));
sock_tag->saddr.in6_addr.sin6_addr = sock->ip6->saddr;
sock_tag->saddr.in6_addr.sin6_scope_id = scope_id;
sock_tag->saddr.in6_addr.sin6_flowinfo = ip_htonl(sock->ip6->flowinfo);
IPCOM_SA_LEN_SET(&sock_tag->daddr.in6_addr, sizeof(sock_tag->daddr.in6_addr));
sock_tag->daddr.in6_addr.sin6_addr = sock->ip6->daddr;
sock_tag->daddr.in6_addr.sin6_scope_id = scope_id;
sock_tag->daddr.in6_addr.sin6_flowinfo = ip_htonl(sock->ip6->flowinfo);
}
#endif /* IPCOM_USE_INET6 */
return IPNET_CTRL_SUCCESS;
}
}
return IPNET_CTRL_ENUM_DONE;
}
#ifdef IPCOM_USE_INET6
/*
*===========================================================================
* ipnet_ctrl_fill_nc_entry
*===========================================================================
* Description: Helper function that will return the next neighbor entry
* Parameters: nc_tag - neighbor cache info
* neigh - a neighbor entry
* Returns:
*
*/
IP_STATIC void
ipnet_ctrl_fill_nc_entry(struct Ipnet_tag_nc_entry *nc_tag,
Ipnet_neigh *neigh)
{
struct Ip_sockaddr_dl *dl = &nc_tag->link_addr;
Ipnet_netif *netif = neigh->netif;
nc_tag->ifindex = netif->ipcom.ifindex;
nc_tag->is_router = neigh->is_router;
nc_tag->state = neigh->state;
nc_tag->is_publ = ipnet_neigh_is_publ(neigh);
if (neigh->tmo == IP_NULL)
nc_tag->expires_sec = IPCOM_ADDR_INFINITE;
else
nc_tag->expires_sec = (Ip_u32) (ipnet_timeout_msec_until(neigh->tmo) / 1000);
IPCOM_SA_LEN_SET(dl, sizeof(struct Ip_sockaddr_dl));
dl->sdl_family = IP_AF_LINK;
dl->sdl_index = (Ip_u16)netif->ipcom.ifindex;
dl->sdl_nlen = (Ip_u8) 0;
dl->sdl_alen = (Ip_u8) netif->ipcom.link_addr_size;
dl->sdl_type = (Ip_u8) netif->ipcom.type;
ipcom_memcpy(IP_SOCKADDR_DL_LLADDR(dl),
neigh->lladdr,
netif->ipcom.link_addr_size);
}
/*
*===========================================================================
* ipnet_ctrl_ip6_nc
*===========================================================================
* Description: Sets and gets IPv6 neighbor cache entries.
* Parameters: tag - Contains the information to set/add/delete.
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC int
ipnet_ctrl_ip6_nc(struct Ipnet_tag *tag)
{
struct Ipnet_tag_nc_entry *nc_tag = (struct Ipnet_tag_nc_entry*) tag;
Ipnet_neigh *neigh;
Ipnet_netif *netif = IP_NULL;
Ipnet_route_entry *rt = IP_NULL;
int ret;
if (tag->size < sizeof(*nc_tag))
{
tag->size = sizeof(*nc_tag);
return -IP_ERRNO_ENOSPC;
}
if (nc_tag->ifindex != 0)
{
netif = ipnet_if_indextonetif(nc_tag->vr_index, nc_tag->ifindex);
if (netif == IP_NULL)
/* The specified interface does not exist */
return -IP_ERRNO_ENXIO;
nc_tag->vr_index = netif->vr_index;
}
else
{
/* Use the interface specified by the FIB */
ret = ipnet_route_raw_lookup(IP_AF_INET6,
nc_tag->vr_index,
IPCOM_ROUTE_TABLE_DEFAULT,
0,
&nc_tag->addr.sin6_addr,
nc_tag->addr.sin6_scope_id,
0,
&rt);
if (ret < 0)
return ret;
netif = rt->netif;
}
switch (tag->type)
{
case IPNET_CTRL_GET_NC_ENTRY:
neigh = ipnet_neigh_get(IP_AF_INET6,
&nc_tag->addr.sin6_addr,
netif,
IPNET_NEIGH_NO_CREATE);
if (neigh == IP_NULL)
return -IP_ERRNO_EADDRNOTAVAIL;
ipnet_ctrl_fill_nc_entry(nc_tag, neigh);
ipnet_neigh_release(neigh);
return IPNET_CTRL_SUCCESS;
case IPNET_CTRL_ADD_NC_ENTRY:
neigh = ipnet_neigh_get(IP_AF_INET6,
&nc_tag->addr.sin6_addr,
netif,
IPNET_NEIGH_CAN_CREATE);
if (neigh == IP_NULL)
return -IP_ERRNO_ENOMEM;
ipnet_neigh_set_lladdr(neigh, IP_SOCKADDR_DL_LLADDR(&nc_tag->link_addr));
ipnet_neigh_set_state(neigh, IPNET_ND_REACHABLE);
if (nc_tag->expires_sec == IPCOM_ADDR_INFINITE)
ipnet_neigh_set_perm(neigh, IP_TRUE);
ipnet_neigh_release(neigh);
return IPNET_CTRL_SUCCESS;
case IPNET_CTRL_DEL_NC_ENTRY:
neigh = ipnet_neigh_get(IP_AF_INET6,
&nc_tag->addr.sin6_addr,
netif,
IPNET_NEIGH_NO_CREATE);
if (neigh == IP_NULL)
return -IP_ERRNO_ENOTFOUND;
ipnet_neigh_set_state(neigh, IPNET_ND_DEAD);
ipnet_neigh_release(neigh);
return IPNET_CTRL_SUCCESS;
default:
break;
}
return -IP_ERRNO_EINVAL;
}
/*
*===========================================================================
* ipnet_ctrl_ip6_prefix
*===========================================================================
* Description: Sets and gets IPv6 address prefixes.
* Parameters: tag - Contains the information to set/add/delete.
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC int
ipnet_ctrl_ip6_prefix(struct Ipnet_tag *tag)
{
struct Ipnet_tag_prefix_entry *prefix_tag = (struct Ipnet_tag_prefix_entry*) tag;
Ipnet_netif *netif;
Ip_bool has_moved_to_next = IP_FALSE;
Ipnet_route_entry *rt = IP_NULL;
struct Ip_sockaddr_in6 sa_mask;
int ret;
if (tag->size < sizeof(*prefix_tag))
{
tag->size = sizeof(*prefix_tag);
return -IP_ERRNO_ENOSPC;
}
if (prefix_tag->ifindex == 0
&& tag->type != IPNET_CTRL_NEW_ENUM_PREFIX_ENTRY
&& tag->type != IPNET_CTRL_CONT_ENUM_PREFIX_ENTRY)
return -IP_ERRNO_EINVAL;
if (prefix_tag->ifindex != 0)
{
netif = ipnet_if_indextonetif(prefix_tag->vr_index, prefix_tag->ifindex);
if (netif == IP_NULL)
/* The specified interface does not exist */
return -IP_ERRNO_ENXIO;
}
switch (tag->type)
{
case IPNET_CTRL_CONT_ENUM_PREFIX_ENTRY :
ret = ipnet_route_raw_lookup(IP_AF_INET6,
prefix_tag->vr_index,
IPCOM_ROUTE_TABLE_DEFAULT,
0,
&prefix_tag->prefix.sin6_addr,
prefix_tag->prefix.sin6_scope_id,
prefix_tag->ifindex,
&rt);
if (ret < 0)
return ret;
while (IP_BIT_ISFALSE(rt->hdr.flags, IPNET_RTF_X_AUTO))
{
rt = ipnet_route_next_entry(rt);
if (rt == IP_NULL)
return IPNET_CTRL_ENUM_DONE;
}
/* Fall through */
case IPNET_CTRL_NEW_ENUM_PREFIX_ENTRY :
if (rt == IP_NULL)
{
rt = ipnet_route_first_entry(IP_AF_INET6, prefix_tag->vr_index, IPCOM_ROUTE_TABLE_DEFAULT);
if (rt == IP_NULL)
return IPNET_CTRL_ENUM_DONE;
}
do {
while (!has_moved_to_next
|| IP_BIT_ISFALSE(rt->hdr.flags, IPNET_RTF_X_AUTO))
{
rt = ipnet_route_next_entry(rt);
if (rt == IP_NULL)
return IPNET_CTRL_ENUM_DONE;
has_moved_to_next = IP_TRUE;
}
/* Scheduled for delete if the while statements evaluates to true */
} while (rt->metrics.rmx_expire != IPCOM_ADDR_INFINITE
&& IPCOM_IS_LEQ(rt->metrics.rmx_expire, IPNET_SECONDS_ABS));
ipnet_route_key_to_sockaddr(IP_AF_INET6, rt->hdr.key,
(struct Ip_sockaddr *) &prefix_tag->prefix);
ipnet_route_key_to_sockaddr(IP_AF_INET6, rt->hdr.mask,
(struct Ip_sockaddr *) &sa_mask);
prefix_tag->bits = ipcom_sockaddr_to_prefixlen((struct Ip_sockaddr *) &sa_mask);
prefix_tag->ifindex = rt->netif->ipcom.ifindex;
if (rt->metrics.rmx_expire == IPCOM_ADDR_INFINITE)
prefix_tag->expires_sec = IPCOM_ADDR_INFINITE;
else
prefix_tag->expires_sec = (rt->metrics.rmx_expire - IPNET_SECONDS_ABS);
return IPNET_CTRL_SUCCESS;
default:
break;
}
return -IP_ERRNO_EINVAL;
}
/*
*===========================================================================
* ipnet_ctrl_ip6_router
*===========================================================================
* Description: Sets and gets IPv6 default routers.
* Parameters: tag - Contains the information to set/add/delete.
* Returns: 0 = success, <0 = error.
*
*/
IP_STATIC int
ipnet_ctrl_ip6_router(struct Ipnet_tag *tag)
{
struct Ipnet_ipv6_key key;
struct Ip_sockaddr_in6 gw;
struct Ipnet_tag_router_entry *router_tag = (struct Ipnet_tag_router_entry*) tag;
int ret = 0;
Ipnet_route_entry *rt = IP_NULL;
Ip_bool force_next = IP_FALSE;
Ipnet_netif *netif;
if (tag->size < sizeof(*router_tag))
{
tag->size = sizeof(*router_tag);
return -IP_ERRNO_ENOSPC;
}
switch (tag->type)
{
case IPNET_CTRL_NEW_ENUM_ROUTER_ENTRY :
ret = ipnet_route_raw_lookup2(IP_AF_INET6,
router_tag->vr_index,
IPCOM_ROUTE_TABLE_DEFAULT,
0,
&ip_in6addr_any,
0,
&ip_in6addr_any,
IP_NULL,
0,
&rt);
/* Fall through */
case IPNET_CTRL_CONT_ENUM_ROUTER_ENTRY :
if (tag->type == IPNET_CTRL_CONT_ENUM_ROUTER_ENTRY)
{
force_next = IP_TRUE;
netif = ipnet_if_indextonetif(router_tag->vr_index, router_tag->ifindex);
if (netif == IP_NULL)
/* The specified interface does not exist */
return -IP_ERRNO_ENXIO;
ipnet_ip6_create_sockaddr(&gw,
&router_tag->addr,
netif->ipcom.ifindex);
ret = ipnet_route_raw_lookup2(IP_AF_INET6,
router_tag->vr_index,
IPCOM_ROUTE_TABLE_DEFAULT,
0,
&ip_in6addr_any,
0,
&ip_in6addr_any,
(struct Ip_sockaddr *) &gw,
router_tag->ifindex,
&rt);
}
if (ret == IPNET_ROUTE_PERFECT_MATCH)
{
/* Select default routes that was dynamically added */
while (rt
&& (rt->gateway == IP_NULL
|| IP_BIT_ISSET(rt->hdr.flags, IPNET_RTF_STATIC)
|| force_next))
{
rt = rt->next;
force_next = IP_FALSE;
}
}
if (ret != IPNET_ROUTE_PERFECT_MATCH || rt == IP_NULL || rt->gateway == IP_NULL)
return IPNET_CTRL_ENUM_DONE;
IPNET_IP6_SET_ADDR(&router_tag->addr, &((struct Ip_sockaddr_in6 *) rt->gateway)->sin6_addr);
if (rt->metrics.rmx_expire == IPCOM_ADDR_INFINITE)
router_tag->expires_sec = IPCOM_ADDR_INFINITE;
else
router_tag->expires_sec = rt->metrics.rmx_expire - IPNET_SECONDS_ABS;
router_tag->ifindex = rt->netif->ipcom.ifindex;
return IPNET_CTRL_SUCCESS;
case IPNET_CTRL_DEL_ROUTER_ENTRY :
ipcom_memset(&key, 0, sizeof(key));
ipnet_ip6_create_sockaddr(&gw,
&router_tag->addr,
router_tag->ifindex);
if (ipnet_route_delete2(IP_AF_INET6,
router_tag->vr_index,
IPCOM_ROUTE_TABLE_DEFAULT,
&key,
&key,
(struct Ip_sockaddr *) &gw,
router_tag->ifindex,
ipnet_get_effective_pid(),
0,
IP_FALSE) < 0)
{
return -IP_ERRNO_ENOTFOUND;
}
return IPNET_CTRL_SUCCESS;
default:
break;
}
return -IP_ERRNO_EINVAL;
}
#endif /* IPCOM_USE_INET6 */
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_ctrl_islocked
*===========================================================================
* Description: SNMP helper function to access ndp tables
* Code semaphore must be locked.
* Parameters: tag - The data to set or get.
* Returns: 0 = succcess, -1 = error
* (get error code from ipcom_errno)
*
*/
#if defined(IPCOM_USE_MIB2) && defined(IPCOM_USE_INET6)
IP_GLOBAL int
ipnet_ctrl_islocked(struct Ipnet_tag *tag)
{
int retval = -IP_ERRNO_EINVAL;
ip_assert(tag != IP_NULL);
if (IP_BIT_ISSET(tag->type, IPNET_CTRL_NC_ENTRY_BASE))
retval = ipnet_ctrl_ip6_nc(tag);
if (retval < 0)
goto errout;
return retval;
errout:
return ipcom_errno_set(-retval);
}
#endif
/*
*===========================================================================
* ipnet_ctrl_sig
*===========================================================================
* Description: Sets/gets runtime configuration for IPNET.
* Parameters: tag - The data to set or get.
* Returns: 0 = succcess, -1 = error
* (get error code from ipcom_errno)
*
*/
IP_GLOBAL int
ipnet_ctrl_sig(Ipnet_sig *sig)
{
int retval;
struct Ipnet_tag *tag = sig->d.ctrl_tag;
ip_assert(tag != IP_NULL);
#ifdef IPCOM_USE_INET6
if (IP_BIT_ISSET(tag->type, IPNET_CTRL_NC_ENTRY_BASE))
retval = ipnet_ctrl_ip6_nc(tag);
else if (IP_BIT_ISSET(tag->type, IPNET_CTRL_PREFIX_ENTRY_BASE))
retval = ipnet_ctrl_ip6_prefix(tag);
else if (IP_BIT_ISSET(tag->type, IPNET_CTRL_ROUTER_ENTRY_BASE))
retval = ipnet_ctrl_ip6_router(tag);
else
#endif /* IPCOM_USE_INET6 */
if (IP_BIT_ISSET(tag->type, IPNET_CTRL_SOCK_BASE))
retval = ipnet_ctrl_sock(tag);
else
retval = -IP_ERRNO_EINVAL;
return retval;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/