705 lines
21 KiB
C
705 lines
21 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_rtnetlink_rule.c,v $ $Revision: 1.15.10.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_rtnetlink_rule.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation Jonas Rendel <Jonas.Rendel@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
* Contains netlink handlers for managing virtual routers, tables and
|
|
* interface rules.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifndef IPCOM_KERNEL
|
|
#define IPCOM_KERNEL
|
|
#endif
|
|
#include "ipnet_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPNET_USE_NETLINK
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom.h>
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_sock2.h>
|
|
#include <ipcom_route.h>
|
|
#include <ipcom_errno.h>
|
|
|
|
#include "ipnet_h.h"
|
|
#include "ipnet_ctrl.h"
|
|
#include "ipnet_route.h"
|
|
#include "ipnet_netlink.h"
|
|
#include "ipnet_netlink_h.h"
|
|
#include "ipnet_loopback.h"
|
|
#include "ipcom_sock.h"
|
|
#ifdef IPCOM_USE_INET6
|
|
#include "ipcom_sock6.h"
|
|
#include "ipnet_ip6.h"
|
|
#endif
|
|
|
|
|
|
#include "ipnet_eth.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IPNET_RTNETLINK_RULE_RTPRIO_TO_PRIO(prio) (Ip_s16)IP_MIN(IPNET_PR_PRIO_MAX, (Ip_s32) ((IPNET_PR_PRIO_MIN + (prio))))
|
|
#define IPNET_RTNETLINK_RULE_PRIO_TO_RTPRIO(prio) (Ip_u32)(-IPNET_PR_PRIO_MIN + (prio))
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipnet_rtnetlink_rule
|
|
{
|
|
struct
|
|
{
|
|
Ip_ptrdiff_t *vr;
|
|
Ip_ptrdiff_t *done;
|
|
Ip_ptrdiff_t *rule;
|
|
Ip_ptrdiff_t aborted;
|
|
Ip_ptrdiff_t cont;
|
|
} state;
|
|
|
|
/* Requested */
|
|
struct Ip_nlmsghdr *nlmsg;
|
|
Ip_u8 family;
|
|
|
|
/* Buffering */
|
|
Ipnet_netlink_mem_t *mem;
|
|
}
|
|
Ipnet_rtnetlink_rule_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_rule_rtrule_to_rule(struct Ip_nlmsghdr *nlmsg,
|
|
Ip_u16 *vr,
|
|
Ip_u8 family,
|
|
struct Ip_rtattr **rta,
|
|
struct Ipnet_policy_routing_rule *mpr)
|
|
{
|
|
struct Ip_fib_rule_hdr *fib = IP_NLMSG_DATA(nlmsg);
|
|
Ip_size_t addrlen;
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (family == IP_AF_INET)
|
|
addrlen = sizeof(struct Ip_in_addr);
|
|
else
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (family == IP_AF_INET6)
|
|
addrlen = sizeof(struct Ip_in6_addr);
|
|
else
|
|
#endif
|
|
{
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
|
|
ipcom_memset(mpr, 0, sizeof(*mpr));
|
|
|
|
mpr->af = family;
|
|
mpr->daddr_prefixlen = fib->dst_len;
|
|
mpr->saddr_prefixlen = fib->src_len;
|
|
|
|
if (*vr == IPCOM_VR_ANY)
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
*vr = ipnet_rtnetlink_vr(rta[IP_FRA_VR - 1], *vr);
|
|
|
|
if (rta[IP_FRA_IFNAME - 1])
|
|
{
|
|
Ipnet_netif *netif = ipnet_if_nametonetif(*vr, IP_RTA_DATA(rta[IP_FRA_IFNAME - 1]));
|
|
if (!netif)
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
mpr->ifindex = netif->ipcom.ifindex;
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_IFINDEX);
|
|
}
|
|
|
|
if (rta[IP_FRA_PRIORITY - 1])
|
|
{
|
|
Ip_s32 tmp = (Ip_s32)IP_GET_32ON8(IP_RTA_DATA(rta[IP_FRA_PRIORITY - 1]));
|
|
mpr->prio = IPNET_RTNETLINK_RULE_RTPRIO_TO_PRIO(tmp);
|
|
}
|
|
|
|
if (rta[IP_FRA_SRC - 1])
|
|
{
|
|
ipcom_memcpy(&mpr->saddr, IP_RTA_DATA(rta[IP_FRA_SRC - 1]), addrlen);
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_SADDR);
|
|
}
|
|
|
|
if (rta[IP_FRA_DST - 1])
|
|
{
|
|
ipcom_memcpy(&mpr->daddr, IP_RTA_DATA(rta[IP_FRA_DST - 1]), addrlen);
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_DADDR);
|
|
}
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (rta[IP_FRA_SCOPE - 1])
|
|
{
|
|
mpr->scope = ipnet_rtnetlink_ip6_rtscope_to_scope(IP_GET_32ON8(IP_RTA_DATA(rta[IP_FRA_SCOPE - 1])));
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_SCOPE);
|
|
}
|
|
#endif
|
|
|
|
if (fib->tos)
|
|
{
|
|
mpr->ds = fib->tos;
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_DS);
|
|
}
|
|
|
|
/**/
|
|
if (rta[IP_FRA_ID - 1])
|
|
mpr->id = IP_GET_32ON8(IP_RTA_DATA(rta[IP_FRA_ID - 1]));
|
|
|
|
if (IP_BIT_ISSET(fib->flags, IP_FIB_RULE_FIND_SADDR))
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_RTKEYSADDR);
|
|
|
|
if (IP_BIT_ISSET(fib->flags, IP_FIB_RULE_INVERT))
|
|
IP_BIT_SET(mpr->mask, IPNET_PR_RULE_INVERTED);
|
|
|
|
if (rta[IP_FRA_TABLE - 1])
|
|
mpr->table = IP_GET_32ON8(IP_RTA_DATA(rta[IP_FRA_TABLE - 1]));
|
|
else
|
|
mpr->table = fib->table;
|
|
mpr->table = IPCOM_ROUTE_TABLE_GET(mpr->table);
|
|
|
|
mpr->action = fib->action;
|
|
switch (mpr->action)
|
|
{
|
|
case IP_FR_ACT_TO_TBL:
|
|
case IP_FR_ACT_PROHIBIT:
|
|
case IP_FR_ACT_UNREACHABLE:
|
|
case IP_FR_ACT_BLACKHOLE:
|
|
return 0;
|
|
default:
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_rtnetlink_ip4_rule_fill_info
|
|
*===========================================================================
|
|
* Description: Fill a NETLINK message with info about a route.
|
|
* Parameters: data - Message buffer.
|
|
* rt - IPNET route entry.
|
|
* pid - NETLINK caller pid.
|
|
* len - Available buffer length
|
|
*
|
|
* Returns: 0 - Success
|
|
* <0 - Failure
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipnet_rtnetlink_rule_fill_info(Ipnet_netlink_mem_t *mem,
|
|
Ip_u16 vr,
|
|
Ip_u8 family,
|
|
struct Ipnet_policy_routing_rule *rule,
|
|
Ip_u32 seq,
|
|
int event,
|
|
Ip_u16 eflags)
|
|
{
|
|
struct Ip_nlmsghdr *nlh;
|
|
Ip_u32 tmp32;
|
|
Ip_size_t addrlen;
|
|
struct Ip_fib_rule_hdr *fib;
|
|
|
|
nlh = ipnet_netlink_nlmsg_sz_begin(mem, seq, event, eflags);
|
|
if (!nlh)
|
|
return -1;
|
|
|
|
fib = ipnet_netlink_sz_put(mem, IP_NULL, sizeof (*fib));
|
|
if (!fib)
|
|
return -1;
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
if (family == IP_AF_INET)
|
|
addrlen = sizeof(struct Ip_in_addr);
|
|
else
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (family == IP_AF_INET6)
|
|
addrlen = sizeof(struct Ip_in6_addr);
|
|
else
|
|
#endif
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
ipcom_memset(fib, 0, sizeof(*fib));
|
|
|
|
/* Add route message header */
|
|
fib->family = family;
|
|
|
|
/* Only have unicast right now */
|
|
fib->action = rule->action;
|
|
|
|
/* Convert to 0 ... MAX */
|
|
{
|
|
tmp32 = (Ip_u32)(-IPNET_PR_PRIO_MIN + rule->prio);
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_PRIORITY, sizeof(tmp32), &tmp32))
|
|
return -1;
|
|
}
|
|
|
|
tmp32 = vr;
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_VR, sizeof(tmp32), &tmp32))
|
|
return -1;
|
|
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_ID, sizeof(rule->id), &rule->id))
|
|
return -1;
|
|
|
|
/* Store the source & destination */
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_DS))
|
|
fib->tos = rule->ds;
|
|
|
|
/* Store the source & destination */
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_DADDR))
|
|
{
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_DST, addrlen, &rule->daddr))
|
|
return -1;
|
|
|
|
fib->dst_len = rule->daddr_prefixlen;
|
|
}
|
|
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_SADDR))
|
|
{
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_SRC, addrlen, &rule->saddr))
|
|
return -1;
|
|
|
|
fib->src_len = rule->saddr_prefixlen;
|
|
}
|
|
|
|
if (fib->action == IP_FR_ACT_TO_TBL)
|
|
{
|
|
fib->table = (Ip_u8) rule->table;
|
|
/* Store table */
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_TABLE, sizeof(rule->table), &rule->table))
|
|
return -1;
|
|
}
|
|
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_IFINDEX))
|
|
{
|
|
/* Put destination address */
|
|
Ipnet_netif *netif = ipnet_if_indextonetif(vr, rule->ifindex);
|
|
if (netif)
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_IFNAME, ipcom_strlen(netif->ipcom.name) + 1, netif->ipcom.name))
|
|
return -1;
|
|
}
|
|
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (family == IP_AF_INET6 && IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_SCOPE))
|
|
{
|
|
tmp32 = ipnet_rtnetlink_ip6_scope_to_rtscope(rule->scope);
|
|
if (!ipnet_rtnetlink_rta_sz_put(mem, IP_FRA_SCOPE, sizeof(tmp32), &tmp32))
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_RTKEYSADDR))
|
|
IP_BIT_SET(fib->flags, IP_FIB_RULE_FIND_SADDR);
|
|
|
|
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_INVERTED))
|
|
IP_BIT_SET(fib->flags, IP_FIB_RULE_INVERT);
|
|
|
|
/* Done */
|
|
return ipnet_netlink_nlmsg_sz_end(mem, nlh);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_rtnetlink_route_foreach_vr
|
|
*===========================================================================
|
|
* Description: Hash table foreach callback. Called once for each virtual
|
|
* router that exists in the system.
|
|
* Parameters: rtab - route table
|
|
* param - callback parameters.
|
|
* Returns: -
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipnet_rtnetlink_rule_foreach_vr(Ipcom_route *rtab, Ipnet_rtnetlink_rule_t *param)
|
|
{
|
|
Ip_u16 vr = IPNET_ROUTE_GET_VR(rtab);
|
|
Ipnet_route_policy_rule *r = IP_NULL;
|
|
|
|
/* This traversal is already aborted */
|
|
if (param->state.aborted)
|
|
return;
|
|
|
|
/* Only handle rtabs of selected address family */
|
|
if (IPNET_ROUTE_GET_FAMILY(rtab) != param->family)
|
|
return;
|
|
|
|
/* Go for the defaults to get current VR's */
|
|
if (IPNET_ROUTE_GET_TABLE(rtab) != IPCOM_ROUTE_TABLE_DEFAULT)
|
|
return;
|
|
|
|
/*
|
|
* If this is a trailer message buffer, make sure it
|
|
* starts dumping where the last message ended
|
|
*/
|
|
if (param->state.cont)
|
|
{
|
|
Ipnet_route_policy_rule *rtmp = (Ipnet_route_policy_rule*)(*param->state.rule);
|
|
/* Verify current state */
|
|
if (*param->state.vr != vr)
|
|
return;
|
|
|
|
r = ipnet_route_policy_get_rule_chain(param->family, vr);
|
|
/**/
|
|
if (r)
|
|
{
|
|
while (r != IP_NULL && r != rtmp)
|
|
r = IPCOM_LIST_NEXT(&r->list);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = ipnet_route_policy_get_rule_chain(param->family, vr);
|
|
}
|
|
|
|
/* Reset the continue variable; we're on the move again */
|
|
param->state.cont = 0;
|
|
|
|
if (r == IP_NULL)
|
|
return;
|
|
|
|
do
|
|
{
|
|
/* Time to start dump info */
|
|
if (ipnet_rtnetlink_rule_fill_info(param->mem, vr, param->family, &r->rule, param->nlmsg->nlmsg_seq, IP_RTM_NEWRULE, IP_NLM_F_MULTI) < 0)
|
|
goto aborted;
|
|
} while ((r = IPCOM_LIST_NEXT(&r->list)) != IP_NULL);
|
|
|
|
return;
|
|
|
|
aborted:
|
|
param->state.aborted = 1;
|
|
*param->state.rule = (Ip_ptrdiff_t)r;
|
|
*param->state.vr = (Ip_ptrdiff_t)vr;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_rtnetlink_rule_event
|
|
*===========================================================================
|
|
* Description: Status of a network rule has changed, create a rule
|
|
* event on NETLNK..
|
|
* Parameters: netif - The interface.
|
|
* Returns: -
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipnet_rtnetlink_rule_event(struct Ipnet_policy_routing_rule *mpr,
|
|
Ip_u16 vr,
|
|
Ip_pid_t pid,
|
|
int event)
|
|
{
|
|
Ipcom_pkt *pkt = IP_NULL;
|
|
Ipnet_netlink_mem_t mem;
|
|
int ret = -1;
|
|
int group = 0;
|
|
|
|
if (!ipnet_netlink_pkt_alloc(&pkt, IP_NULL, IP_TRUE, &mem, 512))
|
|
return;
|
|
|
|
/* Must explicitly switch to the correct VR here */
|
|
pkt->vr_index = mem.vr = vr;
|
|
mem.pid = pid;
|
|
|
|
ret = ipnet_rtnetlink_rule_fill_info(&mem,
|
|
vr,
|
|
mpr->af,
|
|
mpr,
|
|
0,
|
|
event,
|
|
0);
|
|
#ifdef IPCOM_USE_INET
|
|
if (mpr->af == IP_AF_INET)
|
|
group = IP_RTNLGRP_IPV4_RULE;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (mpr->af == IP_AF_INET6)
|
|
group = IP_RTNLGRP_IPV6_RULE;
|
|
#endif
|
|
|
|
if (ret < 0)
|
|
ipcom_pkt_free(pkt);
|
|
else
|
|
{
|
|
pkt->end += ret;
|
|
|
|
/* We're done; do report this pkt */
|
|
ipnet_rtnetlink_broadcast(pkt, group);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
*==========================================================================
|
|
* ipnet_rtnetlink_rule_dump
|
|
*===========================================================================
|
|
* Description: Get interface info via NETLINK
|
|
* Parameters: data - Message payload.
|
|
* len - Length of message.
|
|
* cb - NETLINK callback entry
|
|
*
|
|
* Returns: 0 - Success
|
|
* <0 - Failure
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_rule_dump_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlmsg,
|
|
int family,
|
|
Ip_ptrdiff_t *args)
|
|
|
|
{
|
|
Ip_ptrdiff_t *done = &args[0];
|
|
Ip_ptrdiff_t *s_vr = &args[1];
|
|
Ip_ptrdiff_t *s_rule = &args[2];
|
|
Ip_ptrdiff_t *s_continue = &args[3];
|
|
Ipnet_rtnetlink_rule_t param;
|
|
|
|
param.nlmsg = nlmsg;
|
|
param.mem = mem;
|
|
|
|
if (*done)
|
|
goto exit_out;
|
|
|
|
param.family = (Ip_u8) family;
|
|
param.state.aborted = 0;
|
|
param.state.done = done;
|
|
param.state.vr = s_vr;
|
|
param.state.rule = s_rule;
|
|
param.state.cont = *s_continue;
|
|
|
|
/* */
|
|
ipcom_hash_for_each(ipnet->rtabs,
|
|
(Ipcom_hash_foreach_cb_func)ipnet_rtnetlink_rule_foreach_vr,
|
|
¶m);
|
|
|
|
/* Are we aborted? */
|
|
*s_continue = param.state.aborted;
|
|
|
|
/* If not aborted; we're done */
|
|
if (!param.state.aborted)
|
|
*done = 1;
|
|
|
|
exit_out:
|
|
return (int) param.mem->used;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_rtnetlink_rule_newrule_family
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_rule_newrule_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlmsg,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
struct Ipnet_policy_routing_rule mpr;
|
|
Ip_u16 vr;
|
|
int ret;
|
|
|
|
vr = mem->vr;
|
|
|
|
/**/
|
|
ret = ipnet_rtnetlink_rule_rtrule_to_rule(nlmsg, &vr, (Ip_u8) family, rta, &mpr);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
/* Add this rule */
|
|
return ipnet_route_policy_ioctl(mem->pid, vr, IPNET_SIOCSPRRULE, &mpr);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipnet_rtnetlink_rule_newrule_family
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipnet_rtnetlink_rule_delrule_family(Ipnet_netlink_mem_t *mem,
|
|
struct Ip_nlmsghdr *nlmsg,
|
|
struct Ip_rtattr **rta,
|
|
int family)
|
|
{
|
|
struct Ipnet_policy_routing_rule mpr;
|
|
Ip_u16 vr;
|
|
int ret;
|
|
|
|
vr = mem->vr;
|
|
|
|
/**/
|
|
ret = ipnet_rtnetlink_rule_rtrule_to_rule(nlmsg, &vr, (Ip_u8) family, rta, &mpr);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (mpr.id == IPNET_PR_ID_NONE)
|
|
{
|
|
Ipnet_route_policy_rule *r;
|
|
|
|
/* Try find this rule */
|
|
r = ipnet_route_policy_get_rule_chain(family, vr);
|
|
for (; r != IP_NULL; r = IPCOM_LIST_NEXT(&r->list))
|
|
{
|
|
mpr.id = r->rule.id;
|
|
|
|
/* Not the same table */
|
|
if (mpr.table != r->rule.table)
|
|
continue;
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_DS))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_DS) || r->rule.ds != mpr.ds)
|
|
continue;
|
|
}
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_SADDR))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_SADDR) ||
|
|
r->rule.saddr_prefixlen != mpr.saddr_prefixlen ||
|
|
!ipnet_route_key_cmp(&r->rule.saddr, &mpr.saddr, r->rule.saddr_prefixlen))
|
|
continue;
|
|
}
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_DADDR))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_DADDR) ||
|
|
r->rule.daddr_prefixlen != mpr.daddr_prefixlen ||
|
|
!ipnet_route_key_cmp(&r->rule.daddr, &mpr.daddr, r->rule.daddr_prefixlen))
|
|
continue;
|
|
}
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_RTKEYSADDR))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_RTKEYSADDR))
|
|
continue;
|
|
}
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_IFINDEX))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_IFINDEX) || r->rule.ifindex != mpr.ifindex)
|
|
continue;
|
|
}
|
|
|
|
/* Do item for item compare */
|
|
if (IP_BIT_ISSET(mpr.mask, IPNET_PR_RULE_SCOPE))
|
|
{
|
|
if (IP_BIT_ISFALSE(r->rule.mask, IPNET_PR_RULE_SCOPE) || r->rule.scope != mpr.scope)
|
|
continue;
|
|
}
|
|
|
|
/* Passed all */
|
|
break;
|
|
}
|
|
|
|
if (!r)
|
|
return -IP_ERRNO_ENOENT;
|
|
}
|
|
|
|
/* Add this rule */
|
|
return ipnet_route_policy_ioctl(mem->pid, vr, IPNET_SIOCDPRRULE, &mpr);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#endif /* IPNET_USE_NETLINK */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|