|
Packit Service |
aa3af4 |
/*
|
|
Packit Service |
aa3af4 |
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* This software is available to you under a choice of one of two
|
|
Packit Service |
aa3af4 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit Service |
aa3af4 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit Service |
aa3af4 |
* COPYING in the main directory of this source tree, or the
|
|
Packit Service |
aa3af4 |
* BSD license below:
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* Redistribution and use in source and binary forms, with or
|
|
Packit Service |
aa3af4 |
* without modification, are permitted provided that the following
|
|
Packit Service |
aa3af4 |
* conditions are met:
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* - Redistributions of source code must retain the above
|
|
Packit Service |
aa3af4 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
aa3af4 |
* disclaimer.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* - Redistributions in binary form must reproduce the above
|
|
Packit Service |
aa3af4 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
aa3af4 |
* disclaimer in the documentation and/or other materials
|
|
Packit Service |
aa3af4 |
* provided with the distribution.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit Service |
aa3af4 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit Service |
aa3af4 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit Service |
aa3af4 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit Service |
aa3af4 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit Service |
aa3af4 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit Service |
aa3af4 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit Service |
aa3af4 |
* SOFTWARE.
|
|
Packit Service |
aa3af4 |
*/
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
#include <stdio.h>
|
|
Packit Service |
aa3af4 |
#include <stdint.h>
|
|
Packit Service |
aa3af4 |
#include <string.h>
|
|
Packit Service |
aa3af4 |
#include <stdlib.h>
|
|
Packit Service |
aa3af4 |
#include <sys/ioctl.h>
|
|
Packit Service |
aa3af4 |
#include <sys/socket.h>
|
|
Packit Service |
aa3af4 |
#include <linux/rtnetlink.h>
|
|
Packit Service |
aa3af4 |
#include <linux/netlink.h>
|
|
Packit Service |
aa3af4 |
#include <linux/fib_rules.h>
|
|
Packit Service |
aa3af4 |
#include <netinet/in.h>
|
|
Packit Service |
aa3af4 |
#include <netinet/ether.h>
|
|
Packit Service |
aa3af4 |
#include <arpa/inet.h>
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
#include "utils/bullseye.h"
|
|
Packit Service |
aa3af4 |
#include "utils/lock_wrapper.h"
|
|
Packit Service |
aa3af4 |
#include "vlogger/vlogger.h"
|
|
Packit Service |
aa3af4 |
#include "vma/util/vtypes.h"
|
|
Packit Service |
aa3af4 |
#include "vma/util/utils.h"
|
|
Packit Service |
aa3af4 |
#include "vma/util/if.h"
|
|
Packit Service |
aa3af4 |
#include "rule_table_mgr.h"
|
|
Packit Service |
aa3af4 |
#include "vma/sock/socket_fd_api.h"
|
|
Packit Service |
aa3af4 |
#include "vma/sock/sock-redirect.h"
|
|
Packit Service |
aa3af4 |
#include "ip_address.h"
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// debugging macros
|
|
Packit Service |
aa3af4 |
#define MODULE_NAME "rrm:"
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
#define rr_mgr_if_logpanic __log_panic
|
|
Packit Service |
aa3af4 |
#define rr_mgr_logerr __log_err
|
|
Packit Service |
aa3af4 |
#define rr_mgr_logwarn __log_warn
|
|
Packit Service |
aa3af4 |
#define rr_mgr_loginfo __log_info
|
|
Packit Service |
aa3af4 |
#define rr_mgr_logdbg __log_dbg
|
|
Packit Service |
aa3af4 |
#define rr_mgr_logfunc __log_func
|
|
Packit Service |
aa3af4 |
#define rr_mgr_logfuncall __log_funcall
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rule_table_mgr* g_p_rule_table_mgr = NULL;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rule_table_mgr::rule_table_mgr() : netlink_socket_mgr<rule_val>(RULE_DATA_TYPE), cache_table_mgr<route_rule_table_key, std::deque<rule_val*>*>("rule_table_mgr")
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("");
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
//Read Rule table from kernel and save it in local variable.
|
|
Packit Service |
aa3af4 |
update_tbl();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
//Print table
|
|
Packit Service |
aa3af4 |
print_val_tbl();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("Done");
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
//This function uses Netlink to get routing rules saved in kernel then saved it locally.
|
|
Packit Service |
aa3af4 |
void rule_table_mgr::update_tbl()
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
auto_unlocker lock(m_lock);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
netlink_socket_mgr<rule_val>::update_tbl();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
return;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Parse received rule entry into custom object (rule_val).
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// nl_header : object that contain rule entry.
|
|
Packit Service |
aa3af4 |
// p_val : custom object that contain parsed rule data.
|
|
Packit Service |
aa3af4 |
// return true if its not related to local or default table, false otherwise.
|
|
Packit Service |
aa3af4 |
bool rule_table_mgr::parse_enrty(nlmsghdr *nl_header, rule_val *p_val)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
int len;
|
|
Packit Service |
aa3af4 |
struct rtmsg *rt_msg;
|
|
Packit Service |
aa3af4 |
struct rtattr *rt_attribute;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// get rule entry header
|
|
Packit Service |
aa3af4 |
rt_msg = (struct rtmsg *) NLMSG_DATA(nl_header);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// we are not concerned about the local and default rule table
|
|
Packit Service |
aa3af4 |
if (rt_msg->rtm_family != AF_INET || rt_msg->rtm_table == RT_TABLE_LOCAL)
|
|
Packit Service |
aa3af4 |
return false;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
p_val->set_protocol(rt_msg->rtm_protocol);
|
|
Packit Service |
aa3af4 |
p_val->set_scope(rt_msg->rtm_scope);
|
|
Packit Service |
aa3af4 |
p_val->set_type(rt_msg->rtm_type);
|
|
Packit Service |
aa3af4 |
p_val->set_tos(rt_msg->rtm_tos);
|
|
Packit Service |
aa3af4 |
p_val->set_table_id(rt_msg->rtm_table);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
len = RTM_PAYLOAD(nl_header);
|
|
Packit Service |
aa3af4 |
rt_attribute = (struct rtattr *) RTM_RTA(rt_msg);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
for (;RTA_OK(rt_attribute, len);rt_attribute=RTA_NEXT(rt_attribute,len)) {
|
|
Packit Service |
aa3af4 |
parse_attr(rt_attribute, p_val);
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
p_val->set_state(true);
|
|
Packit Service |
aa3af4 |
p_val->set_str();
|
|
Packit Service |
aa3af4 |
return true;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Parse received rule attribute for given rule.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// rt_attribute : object that contain rule attribute.
|
|
Packit Service |
aa3af4 |
// p_val : custom object that contain parsed rule data.
|
|
Packit Service |
aa3af4 |
void rule_table_mgr::parse_attr(struct rtattr *rt_attribute, rule_val *p_val)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
switch (rt_attribute->rta_type) {
|
|
Packit Service |
aa3af4 |
case FRA_PRIORITY:
|
|
Packit Service |
aa3af4 |
p_val->set_priority(*(uint32_t *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
case FRA_DST:
|
|
Packit Service |
aa3af4 |
p_val->set_dst_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
case FRA_SRC:
|
|
Packit Service |
aa3af4 |
p_val->set_src_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
case FRA_IFNAME:
|
|
Packit Service |
aa3af4 |
p_val->set_iif_name((char *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
case FRA_TABLE:
|
|
Packit Service |
aa3af4 |
p_val->set_table_id(*(uint32_t *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
#if DEFINED_FRA_OIFNAME
|
|
Packit Service |
aa3af4 |
case FRA_OIFNAME:
|
|
Packit Service |
aa3af4 |
p_val->set_oif_name((char *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
#endif
|
|
Packit Service |
aa3af4 |
default:
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("got undetected rta_type %d %x", rt_attribute->rta_type, *(uint32_t *)RTA_DATA(rt_attribute));
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Create rule entry object for given destination key and fill it with matching rule value from rule table.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// key : key object that contain information about destination.
|
|
Packit Service |
aa3af4 |
// obs : object that contain observer for specific rule entry.
|
|
Packit Service |
aa3af4 |
// Returns created rule entry object.
|
|
Packit Service |
aa3af4 |
rule_entry* rule_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("");
|
|
Packit Service |
aa3af4 |
NOT_IN_USE(obs);
|
|
Packit Service |
aa3af4 |
rule_entry* p_ent = new rule_entry(key);
|
|
Packit Service |
aa3af4 |
update_entry(p_ent);
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("new entry %p created successfully", p_ent);
|
|
Packit Service |
aa3af4 |
return p_ent;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Update invalid rule entry with matching rule value from rule table.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// p_ent : rule entry that will be updated if it is invalid.
|
|
Packit Service |
aa3af4 |
void rule_table_mgr::update_entry(rule_entry* p_ent)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("entry [%p]", p_ent);
|
|
Packit Service |
aa3af4 |
auto_unlocker lock(m_lock);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("rule_entry is not valid-> update value");
|
|
Packit Service |
aa3af4 |
std::deque<rule_val*>* p_rrv;
|
|
Packit Service |
aa3af4 |
p_ent->get_val(p_rrv);
|
|
Packit Service |
aa3af4 |
/* p_rrv->clear(); TODO for future rule live updates */
|
|
Packit Service |
aa3af4 |
if (!find_rule_val(p_ent->get_key(), p_rrv)) {
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("ERROR: could not find rule val for rule_entry '%s'", p_ent->to_str().c_str());
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Find rule form rule table that match given destination info.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// key : key object that contain information about destination.
|
|
Packit Service |
aa3af4 |
// p_val : list of rule_val object that will contain information about all rule that match destination info
|
|
Packit Service |
aa3af4 |
// Returns true if at least one rule match destination info, false otherwise.
|
|
Packit Service |
aa3af4 |
bool rule_table_mgr::find_rule_val(route_rule_table_key key, std::deque<rule_val*>* &p_val)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
rr_mgr_logfunc("destination info %s:", key.to_str().c_str());
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
for (int index = 0; index < m_tab.entries_num; index++) {
|
|
Packit Service |
aa3af4 |
rule_val* p_val_from_tbl = &m_tab.value[index];
|
|
Packit Service |
aa3af4 |
if (p_val_from_tbl->is_valid() && is_matching_rule(key, p_val_from_tbl)) {
|
|
Packit Service |
aa3af4 |
p_val->push_back(p_val_from_tbl);
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("found rule val[%p]: %s", p_val_from_tbl, p_val_from_tbl->to_str());
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
return !p_val->empty();
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Check matching between given destination info. and specific rule from rule table.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// key : key object that contain information about destination.
|
|
Packit Service |
aa3af4 |
// p_val : rule_val object that contain information about specific rule from rule table
|
|
Packit Service |
aa3af4 |
// Returns true if destination info match rule value, false otherwise.
|
|
Packit Service |
aa3af4 |
bool rule_table_mgr::is_matching_rule(route_rule_table_key key, rule_val* p_val)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
in_addr_t m_dst_ip = key.get_dst_ip();
|
|
Packit Service |
aa3af4 |
in_addr_t m_src_ip = key.get_src_ip();
|
|
Packit Service |
aa3af4 |
uint8_t m_tos = key.get_tos();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
in_addr_t rule_dst_ip = p_val->get_dst_addr();
|
|
Packit Service |
aa3af4 |
in_addr_t rule_src_ip = p_val->get_src_addr();
|
|
Packit Service |
aa3af4 |
uint8_t rule_tos = p_val->get_tos();
|
|
Packit Service |
aa3af4 |
char* rule_iif_name = (char *)p_val->get_iif_name();
|
|
Packit Service |
aa3af4 |
char* rule_oif_name = (char *)p_val->get_oif_name();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
bool is_match = false;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Only destination IP, source IP and TOS are checked with rule, since IIF and OIF is not filled in dst_entry object.
|
|
Packit Service |
aa3af4 |
if ((rule_dst_ip == 0) || (rule_dst_ip == m_dst_ip)) { // Check match in destination IP
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if ((rule_src_ip == 0) || (rule_src_ip == m_src_ip)) { // Check match in source IP
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if ((rule_tos == 0) || (rule_tos == m_tos)) { // Check match in TOS value
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (strcmp(rule_iif_name, "") == 0) { // Check that rule doesn't contain IIF since we can't check match with
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (strcmp(rule_oif_name, "") == 0) { // Check that rule doesn't contain OIF since we can't check match with
|
|
Packit Service |
aa3af4 |
is_match = true;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
return is_match;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Find table ID for given destination info.
|
|
Packit Service |
aa3af4 |
// Parameters:
|
|
Packit Service |
aa3af4 |
// key : key object that contain information about destination.
|
|
Packit Service |
aa3af4 |
// table_id_list : list that will contain table ID for all rule that match destination info
|
|
Packit Service |
aa3af4 |
// Returns true if at least one rule match destination info, false otherwise.
|
|
Packit Service |
aa3af4 |
bool rule_table_mgr::rule_resolve(route_rule_table_key key, std::deque<unsigned char> &table_id_list)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("dst info: '%s'", key.to_str().c_str());
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
std::deque<rule_val*> values;
|
|
Packit Service |
aa3af4 |
std::deque<rule_val*>* p_values = &values;
|
|
Packit Service |
aa3af4 |
auto_unlocker lock(m_lock);
|
|
Packit Service |
aa3af4 |
if (find_rule_val(key, p_values)) {
|
|
Packit Service |
aa3af4 |
for (std::deque<rule_val*>::iterator val = values.begin(); val != values.end(); val++) {
|
|
Packit Service |
aa3af4 |
table_id_list.push_back((*val)->get_table_id());
|
|
Packit Service |
aa3af4 |
rr_mgr_logdbg("dst info: '%s' resolved to table ID '%u'", key.to_str().c_str(), (*val)->get_table_id());
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
return !table_id_list.empty();
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|