Blame keepalived/vrrp/vrrp_iptables.c

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
}