|
Packit |
c22fc9 |
/*
|
|
Packit |
c22fc9 |
* Soft: Keepalived is a failover program for the LVS project
|
|
Packit |
c22fc9 |
* <www.linuxvirtualserver.org>. It monitor & manipulate
|
|
Packit |
c22fc9 |
* a loadbalanced server pool using multi-layer checks.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Part: iptables manipulation directly without invoking iptables program.
|
|
Packit |
c22fc9 |
* This will use ipsets if they are available, in preference to
|
|
Packit |
c22fc9 |
* multiple entries in iptables.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Author: Quentin Armitage, <quentin@armitage.org.uk>
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
c22fc9 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
c22fc9 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
c22fc9 |
* See the GNU General Public License for more details.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
c22fc9 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
c22fc9 |
* as published by the Free Software Foundation; either version
|
|
Packit |
c22fc9 |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Copyright (C) 2001-2017 Alexandre Cassen, <acassen@gmail.com>
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* The way iptables appears to work is that when we do an iptc_init, we get a
|
|
Packit |
c22fc9 |
* snapshot of the iptables table, which internally includes an update number.
|
|
Packit |
c22fc9 |
* When iptc_commit is called, it checks the update number, and if it has been
|
|
Packit |
c22fc9 |
* updated by someone else, returns EAGAIN.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Note: iptc_commit only needs to be called if we are changing something. In
|
|
Packit |
c22fc9 |
* all cases though, iptc_free must be called.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Rules are numbered from 0 - despite what some documentation says
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Note: as insertions/deletions are made, rule numbers are changing.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* See http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/qfunction.html for
|
|
Packit |
c22fc9 |
* some documentation
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include "config.h"
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPTC_LINUX_NET_IF_H_COLLISION_
|
|
Packit |
c22fc9 |
/* Linux 4.5 introduced a namespace collision when including
|
|
Packit |
c22fc9 |
* libiptc/libiptc.h due to both net/if.h and linux/if.h
|
|
Packit |
c22fc9 |
* being included.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* See: http://bugzilla.netfilter.org/show_bug.cgi?id=1067
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Including net/if.h first resolves the issue.
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include <net/if.h>
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPTC_
|
|
Packit |
c22fc9 |
#include <libiptc/libxtc.h>
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
#include <stdint.h>
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
#include <xtables.h>
|
|
Packit |
c22fc9 |
#ifdef USE_LIBIPSET_LINUX_IP_SET_H
|
|
Packit |
c22fc9 |
#include <libipset/linux_ip_set.h>
|
|
Packit |
c22fc9 |
#else
|
|
Packit |
c22fc9 |
#include <linux/netfilter/ipset/ip_set.h>
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
#include <sys/stat.h>
|
|
Packit |
c22fc9 |
#include <sys/vfs.h>
|
|
Packit |
c22fc9 |
#include <linux/magic.h>
|
|
Packit |
c22fc9 |
#include <stdbool.h>
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include "vrrp_iptables.h"
|
|
Packit |
c22fc9 |
#include "vrrp_iptables_calls.h"
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
#include "vrrp_ipset.h"
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
#include "logger.h"
|
|
Packit |
c22fc9 |
#include "global_data.h"
|
|
Packit |
c22fc9 |
#include "memory.h"
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
struct ipt_handle {
|
|
Packit |
c22fc9 |
struct iptc_handle *h4;
|
|
Packit |
c22fc9 |
struct ip6tc_handle *h6;
|
|
Packit |
c22fc9 |
bool updated_v4;
|
|
Packit |
c22fc9 |
bool updated_v6;
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
struct ipset_session* session;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
} ;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* If the chains don't exist, or modules not loaded, we can't use iptables/ip6tables */
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
bool using_libip4tc = false;
|
|
Packit |
c22fc9 |
bool using_libip6tc = false;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
static
|
|
Packit |
c22fc9 |
void add_del_sets(int cmd, bool reload)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (!global_data->using_ipsets)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (cmd == IPADDRESS_ADD)
|
|
Packit |
c22fc9 |
add_ipsets(reload);
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
remove_ipsets();
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static
|
|
Packit |
c22fc9 |
void add_del_rules(int cmd, bool ignore_errors)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
struct iptc_handle *h4;
|
|
Packit |
c22fc9 |
struct ip6tc_handle *h6;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (block_ipv4 &&
|
|
Packit |
c22fc9 |
(global_data->vrrp_iptables_inchain[0] ||
|
|
Packit |
c22fc9 |
global_data->vrrp_iptables_outchain[0])
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
&& using_libip4tc
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
) {
|
|
Packit |
c22fc9 |
if ((h4 = ip4tables_open("filter"))) {
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_inchain[0])
|
|
Packit |
c22fc9 |
ip4tables_add_rules(h4, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_DROP, global_data->vrrp_ipset_address, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0])
|
|
Packit |
c22fc9 |
ip4tables_add_rules(h4, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_DROP, global_data->vrrp_ipset_address, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip4tables_close(h4, true);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (block_ipv6 &&
|
|
Packit |
c22fc9 |
(global_data->vrrp_iptables_inchain[0] ||
|
|
Packit |
c22fc9 |
global_data->vrrp_iptables_outchain[0])
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
&& using_libip6tc
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
) {
|
|
Packit |
c22fc9 |
if ((h6 = ip6tables_open("filter"))) {
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_inchain[0]) {
|
|
Packit |
c22fc9 |
#ifdef HAVE_IPSET_ATTR_IFACE
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_TWO_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_TWO_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_TWO_SRC, XTC_LABEL_DROP, global_data->vrrp_ipset_address_iface6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
#else
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_DROP, global_data->vrrp_ipset_address_iface6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_inchain, APPEND_RULE, IPSET_DIM_ONE, 0, XTC_LABEL_DROP, global_data->vrrp_ipset_address6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0]) {
|
|
Packit |
c22fc9 |
#ifdef HAVE_IPSET_ATTR_IFACE
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_TWO, IPSET_DIM_ONE_SRC, XTC_LABEL_DROP, global_data->vrrp_ipset_address_iface6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
#else
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address_iface6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_DROP, global_data->vrrp_ipset_address_iface6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address6, IPPROTO_ICMPV6, 135, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_ACCEPT, global_data->vrrp_ipset_address6, IPPROTO_ICMPV6, 136, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
ip6tables_add_rules(h6, global_data->vrrp_iptables_outchain, APPEND_RULE, IPSET_DIM_ONE, IPSET_DIM_ONE_SRC, XTC_LABEL_DROP, global_data->vrrp_ipset_address6, IPPROTO_NONE, 0, cmd, ignore_errors);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ip6tables_close(h6, true);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
struct ipt_handle* iptables_open()
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
struct ipt_handle *h = MALLOC(sizeof(struct ipt_handle));
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return h;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
int iptables_close(struct ipt_handle* h)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
int res = 0;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (h->h4)
|
|
Packit |
c22fc9 |
res = ip4tables_close(h->h4, h->updated_v4);
|
|
Packit |
c22fc9 |
if (h->h6)
|
|
Packit |
c22fc9 |
res += ip6tables_close(h->h6, h->updated_v6);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
if (h->session)
|
|
Packit |
c22fc9 |
ipset_session_end(h->session);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
FREE(h);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return res;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void check_chains_exist_lib(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
struct iptc_handle *h4;
|
|
Packit |
c22fc9 |
struct ip6tc_handle *h6;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (block_ipv4) {
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
if (using_libip4tc)
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
h4 = ip4tables_open("filter");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!h4) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "WARNING, ip_tables module not installed - can't filter IPv4 addresses");
|
|
Packit |
c22fc9 |
block_ipv4 = false;
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_inchain[0] &&
|
|
Packit |
c22fc9 |
!ip4tables_is_chain(h4, global_data->vrrp_iptables_inchain)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
|
|
Packit |
c22fc9 |
block_ipv4 = false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0] &&
|
|
Packit |
c22fc9 |
!ip4tables_is_chain(h4, global_data->vrrp_iptables_outchain)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "iptables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
|
|
Packit |
c22fc9 |
block_ipv4 = false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ip4tables_close(h4, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (block_ipv6) {
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
if (using_libip6tc)
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
h6 = ip6tables_open("filter");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!h6) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "WARNING, ip6_tables module not installed - can't filter IPv6 addresses");
|
|
Packit |
c22fc9 |
block_ipv6 = false;
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_inchain[0] &&
|
|
Packit |
c22fc9 |
!ip6tables_is_chain(h6, global_data->vrrp_iptables_inchain)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_inchain);
|
|
Packit |
c22fc9 |
block_ipv6 = false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0] &&
|
|
Packit |
c22fc9 |
!ip6tables_is_chain(h6, global_data->vrrp_iptables_outchain)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "ip6tables chain %s doesn't exist", global_data->vrrp_iptables_outchain);
|
|
Packit |
c22fc9 |
block_ipv6 = false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ip6tables_close(h6, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static int iptables_entry(struct ipt_handle* h, const char* chain_name, unsigned int rulenum, char* target_name, const ip_address_t* src_ip_address, const ip_address_t* dst_ip_address, const char* in_iface, const char* out_iface, uint16_t protocol, uint8_t type, int cmd, bool force)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
int res;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if ((src_ip_address && src_ip_address->ifa.ifa_family == AF_INET) ||
|
|
Packit |
c22fc9 |
(dst_ip_address && dst_ip_address->ifa.ifa_family == AF_INET )) {
|
|
Packit |
c22fc9 |
if (!h->h4)
|
|
Packit |
c22fc9 |
h->h4 = ip4tables_open ("filter");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
res = ip4tables_process_entry(h->h4, chain_name, rulenum, target_name, src_ip_address, dst_ip_address, in_iface, out_iface, protocol, type, cmd, force);
|
|
Packit |
c22fc9 |
if (!res)
|
|
Packit |
c22fc9 |
h->updated_v4 = true ;
|
|
Packit |
c22fc9 |
return res;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if ((src_ip_address && src_ip_address->ifa.ifa_family == AF_INET6) ||
|
|
Packit |
c22fc9 |
(dst_ip_address && dst_ip_address->ifa.ifa_family == AF_INET6)) {
|
|
Packit |
c22fc9 |
if (!h->h6)
|
|
Packit |
c22fc9 |
h->h6 = ip6tables_open ("filter");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
res = ip6tables_process_entry(h->h6, chain_name, rulenum, target_name, src_ip_address, dst_ip_address, in_iface, out_iface, protocol, type, cmd, force);
|
|
Packit |
c22fc9 |
if (!res)
|
|
Packit |
c22fc9 |
h->updated_v6 = true;
|
|
Packit |
c22fc9 |
return res;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return 0;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
handle_iptable_rule_to_NA(ip_address_t *ipaddress, int cmd, void *h, bool force)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
char *ifname = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_inchain[0] == '\0')
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (IN6_IS_ADDR_LINKLOCAL(&ipaddress->u.sin6_addr))
|
|
Packit |
c22fc9 |
ifname = ipaddress->ifp->ifname;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_inchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_ACCEPT, NULL, ipaddress, ifname, NULL,
|
|
Packit |
c22fc9 |
IPPROTO_ICMPV6, 135, cmd, force);
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_inchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_ACCEPT, NULL, ipaddress, ifname, NULL,
|
|
Packit |
c22fc9 |
IPPROTO_ICMPV6, 136, cmd, force);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0] == '\0')
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_outchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_ACCEPT, ipaddress, NULL, NULL, ifname,
|
|
Packit |
c22fc9 |
IPPROTO_ICMPV6, 135, cmd, force);
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_outchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_ACCEPT, ipaddress, NULL, NULL, ifname,
|
|
Packit |
c22fc9 |
IPPROTO_ICMPV6, 136, cmd, force);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
handle_iptable_rule_to_vip_lib(ip_address_t *ipaddress, int cmd, struct ipt_handle *h, bool force)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
char *ifname = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* If iptables for the address family isn't in use, skip */
|
|
Packit |
c22fc9 |
if ((ipaddress->ifa.ifa_family == AF_INET && !block_ipv4) ||
|
|
Packit |
c22fc9 |
(ipaddress->ifa.ifa_family == AF_INET6 && !block_ipv6))
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
if (global_data->using_ipsets)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (!h->session)
|
|
Packit |
c22fc9 |
h->session = ipset_session_start();
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ipset_entry(h->session, cmd, ipaddress);
|
|
Packit |
c22fc9 |
ipaddress->iptable_rule_set = (cmd != IPADDRESS_DEL);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (IP_IS6(ipaddress)) {
|
|
Packit |
c22fc9 |
if (IN6_IS_ADDR_LINKLOCAL(&ipaddress->u.sin6_addr))
|
|
Packit |
c22fc9 |
ifname = ipaddress->ifp->ifname;
|
|
Packit |
c22fc9 |
handle_iptable_rule_to_NA(ipaddress, cmd, h, force);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_inchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_DROP, NULL, ipaddress, ifname, NULL,
|
|
Packit |
c22fc9 |
IPPROTO_NONE, 0, cmd, force);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ipaddress->iptable_rule_set = (cmd != IPADDRESS_DEL);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_data->vrrp_iptables_outchain[0] == '\0')
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
iptables_entry(h, global_data->vrrp_iptables_outchain, APPEND_RULE,
|
|
Packit |
c22fc9 |
XTC_LABEL_DROP, ipaddress, NULL, NULL, ifname,
|
|
Packit |
c22fc9 |
IPPROTO_NONE, 0, cmd, force);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
iptables_remove_structure(bool ignore_errors)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (global_data->using_ipsets) {
|
|
Packit |
c22fc9 |
add_del_rules(IPADDRESS_DEL, ignore_errors);
|
|
Packit |
c22fc9 |
add_del_sets(IPADDRESS_DEL, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
iptables_startup(
|
|
Packit |
c22fc9 |
#ifndef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
__attribute__((unused))
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
bool reload)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
if (!block_ipv4 && !block_ipv6)
|
|
Packit |
c22fc9 |
global_data->using_ipsets = false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_data->using_ipsets) {
|
|
Packit |
c22fc9 |
add_del_sets(IPADDRESS_ADD, reload);
|
|
Packit |
c22fc9 |
add_del_rules(IPADDRESS_ADD, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
iptables_cleanup(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
iptables_remove_structure(true);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* return true if a given file exists within procfs */
|
|
Packit |
c22fc9 |
/* Taken from iptables code */
|
|
Packit |
c22fc9 |
static
|
|
Packit |
c22fc9 |
bool proc_file_exists(const char *filename)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
struct stat s;
|
|
Packit |
c22fc9 |
struct statfs f;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (lstat(filename, &s))
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
if (!S_ISREG(s.st_mode))
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
if (statfs(filename, &f))
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
if (f.f_type != PROC_SUPER_MAGIC)
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return true;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
iptables_init_lib(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (block_ipv4) {
|
|
Packit |
c22fc9 |
if (!proc_file_exists("/proc/net/ip_tables_names") &&
|
|
Packit |
c22fc9 |
!load_xtables_module("ip_tables", "iptables"))
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
using_libip4tc = false;
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
using_libip4tc = true;
|
|
Packit |
c22fc9 |
#else
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
block_ipv4 = false;
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to load module ip_tables");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (block_ipv6) {
|
|
Packit |
c22fc9 |
if (!proc_file_exists("/proc/net/ip6_tables_names") &&
|
|
Packit |
c22fc9 |
!load_xtables_module("ip6_tables", "ip6tables"))
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
using_libip6tc = false;
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
using_libip6tc = true;
|
|
Packit |
c22fc9 |
#else
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
block_ipv6 = false;
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to load module ip_tables");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _LIBIPTC_DYNAMIC_
|
|
Packit |
c22fc9 |
if ((!block_ipv4 && !block_ipv6) ||
|
|
Packit |
c22fc9 |
(!using_libip4tc && !using_libip6tc) ||
|
|
Packit |
c22fc9 |
!iptables_lib_init()) {
|
|
Packit |
c22fc9 |
#ifdef _LIBXTABLES_DYNAMIC_
|
|
Packit |
c22fc9 |
xtables_unload();
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
global_data->using_ipsets = false;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
if (global_data->using_ipsets && !ipset_initialise())
|
|
Packit |
c22fc9 |
global_data->using_ipsets = false;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _LIBXTABLES_DYNAMIC_
|
|
Packit |
c22fc9 |
xtables_unload();
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
iptables_fini(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
#ifdef _HAVE_LIBIPSET_
|
|
Packit |
c22fc9 |
iptables_remove_structure(false);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
}
|