Simple support for nftables (#1117)
* Simple support for nftables Co-authored-by: Chen Zhenge <Mr.ChenWithCapsule@outlook.com>
This commit is contained in:
@@ -38,10 +38,15 @@ else
|
||||
override LDFLAGS += -lssl -lcrypto -lpthread -ldl
|
||||
endif
|
||||
|
||||
ifdef WITH_NFTSET
|
||||
override CFLAGS += -DWITH_NFTSET
|
||||
override LDFLAGS += -lnftables
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
|
||||
$(BIN) : $(OBJS)
|
||||
$(CC) $(OBJS) -o $@ $(LDFLAGS)
|
||||
|
||||
|
||||
187
src/dns_conf.c
187
src/dns_conf.c
@@ -40,6 +40,11 @@ struct dns_ipset_table {
|
||||
};
|
||||
static struct dns_ipset_table dns_ipset_table;
|
||||
|
||||
struct dns_nftset_table {
|
||||
DECLARE_HASHTABLE(nftset, 8);
|
||||
};
|
||||
static struct dns_nftset_table dns_nftset_table;
|
||||
|
||||
struct dns_qtype_soa_table dns_qtype_soa_table;
|
||||
|
||||
struct dns_domain_set_rule_table dns_domain_set_rule_table;
|
||||
@@ -133,6 +138,7 @@ int dns_conf_local_ttl;
|
||||
int dns_conf_force_AAAA_SOA;
|
||||
int dns_conf_force_no_cname;
|
||||
int dns_conf_ipset_timeout_enable;
|
||||
int dns_conf_nftset_timeout_enable;
|
||||
|
||||
char dns_conf_user[DNS_CONF_USRNAME_LEN];
|
||||
|
||||
@@ -170,6 +176,10 @@ static void *_new_dns_rule(enum domain_rule domain_rule)
|
||||
case DOMAIN_RULE_IPSET_IPV6:
|
||||
size = sizeof(struct dns_ipset_rule);
|
||||
break;
|
||||
case DOMAIN_RULE_NFTSET_IP:
|
||||
case DOMAIN_RULE_NFTSET_IP6:
|
||||
size = sizeof(struct dns_nftset_rule);
|
||||
break;
|
||||
case DOMAIN_RULE_NAMESERVER:
|
||||
size = sizeof(struct dns_nameserver_rule);
|
||||
break;
|
||||
@@ -853,6 +863,165 @@ errout:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _config_nftset_table_destroy(void)
|
||||
{
|
||||
struct dns_nftset_name *nftset = NULL;
|
||||
struct hlist_node *tmp = NULL;
|
||||
unsigned long i = 0;
|
||||
|
||||
hash_for_each_safe(dns_nftset_table.nftset, i, tmp, nftset, node)
|
||||
{
|
||||
hlist_del_init(&nftset->node);
|
||||
free(nftset);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dns_nftset_name *_dns_conf_get_nftable(const char *familyname, const char *tablename,
|
||||
const char *setname)
|
||||
{
|
||||
uint32_t key = 0;
|
||||
struct dns_nftset_name *nftset_name = NULL;
|
||||
|
||||
if (familyname == NULL || tablename == NULL || setname == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *hasher[4] = {familyname, tablename, setname, NULL};
|
||||
|
||||
key = hash_string_array(hasher);
|
||||
hash_for_each_possible(dns_nftset_table.nftset, nftset_name, node, key)
|
||||
{
|
||||
if (strncmp(nftset_name->nftfamilyname, familyname, DNS_MAX_NFTSET_FAMILYLEN) == 0 &&
|
||||
strncmp(nftset_name->nfttablename, tablename, DNS_MAX_NFTSET_NAMELEN) == 0 &&
|
||||
strncmp(nftset_name->nftsetname, setname, DNS_MAX_NFTSET_NAMELEN) == 0) {
|
||||
return nftset_name;
|
||||
}
|
||||
}
|
||||
|
||||
nftset_name = malloc(sizeof(*nftset_name));
|
||||
if (nftset_name == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
safe_strncpy(nftset_name->nftfamilyname, familyname, DNS_MAX_NFTSET_FAMILYLEN);
|
||||
safe_strncpy(nftset_name->nfttablename, tablename, DNS_MAX_NFTSET_NAMELEN);
|
||||
safe_strncpy(nftset_name->nftsetname, setname, DNS_MAX_NFTSET_NAMELEN);
|
||||
hash_add(dns_nftset_table.nftset, &nftset_name->node, key);
|
||||
|
||||
return nftset_name;
|
||||
errout:
|
||||
if (nftset_name) {
|
||||
free(nftset_name);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _conf_domain_rule_nftset(char *domain, const char *nftsetname)
|
||||
{
|
||||
struct dns_nftset_rule *nftset_rule = NULL;
|
||||
const struct dns_nftset_name *nftset = NULL;
|
||||
char *copied_name = NULL;
|
||||
enum domain_rule type = 0;
|
||||
int ignore_flag = 0;
|
||||
char *setname = NULL;
|
||||
char *tablename = NULL;
|
||||
|
||||
copied_name = strdup(nftsetname);
|
||||
|
||||
if (copied_name == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
for (char *tok = strtok(copied_name, ","); tok; tok = strtok(NULL, ",")) {
|
||||
if (tok[0] == '#') {
|
||||
if (strncmp(tok, "#6:inet#", 8U) == 0 || strncmp(tok, "#6:ip6#", 7U) == 0) {
|
||||
type = DOMAIN_RULE_NFTSET_IP6;
|
||||
ignore_flag = DOMAIN_FLAG_NFTSET_IP6_IGN;
|
||||
} else if (strncmp(tok, "#4:inet#", 4U) == 0 || strncmp(tok, "#4:ip#", 6U) == 0) {
|
||||
type = DOMAIN_RULE_NFTSET_IP;
|
||||
ignore_flag = DOMAIN_FLAG_NFTSET_IP_IGN;
|
||||
} else {
|
||||
goto errout;
|
||||
}
|
||||
tok += 3;
|
||||
} else {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (strncmp(tok, "-", 1U) == 0) {
|
||||
_config_domain_rule_flag_set(domain, ignore_flag, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
tablename = strpbrk(tok, "#");
|
||||
if (tablename == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
*tablename++ = '\0';
|
||||
setname = strpbrk(tablename, "#");
|
||||
if (setname == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
*setname++ = '\0';
|
||||
|
||||
/* new ipset domain */
|
||||
nftset = _dns_conf_get_nftable(tok, tablename, setname);
|
||||
if (nftset == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
nftset_rule = _new_dns_rule(type);
|
||||
if (nftset_rule == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
nftset_rule->nfttablename = nftset->nfttablename;
|
||||
nftset_rule->nftsetname = nftset->nftsetname;
|
||||
nftset_rule->familyname = nftset->nftfamilyname;
|
||||
|
||||
if (_config_domain_rule_add(domain, type, nftset_rule) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
_dns_rule_put(&nftset_rule->head);
|
||||
}
|
||||
|
||||
goto clear;
|
||||
|
||||
errout:
|
||||
tlog(TLOG_ERROR, "add nftset %s failed", nftsetname);
|
||||
|
||||
if (nftset_rule) {
|
||||
_dns_rule_put(&nftset_rule->head);
|
||||
}
|
||||
|
||||
clear:
|
||||
if (copied_name) {
|
||||
free(copied_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _config_nftset(void *data, int argc, char *argv[])
|
||||
{
|
||||
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||
char *value = argv[1];
|
||||
|
||||
if (argc <= 1) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return _conf_domain_rule_nftset(domain, value);
|
||||
errout:
|
||||
tlog(TLOG_ERROR, "add nftset %s failed", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _conf_domain_rule_address(char *domain, const char *domain_address)
|
||||
{
|
||||
struct dns_rule_address_IPV4 *address_ipv4 = NULL;
|
||||
@@ -1665,6 +1834,7 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
|
||||
{"speed-check-mode", required_argument, NULL, 'c'},
|
||||
{"address", required_argument, NULL, 'a'},
|
||||
{"ipset", required_argument, NULL, 'p'},
|
||||
{"nftset", required_argument, NULL, 's'},
|
||||
{"nameserver", required_argument, NULL, 'n'},
|
||||
{"dualstack-ip-selection", required_argument, NULL, 'd'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
@@ -1750,6 +1920,19 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
|
||||
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
const char *nftsetname = optarg;
|
||||
if (nftsetname == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (_conf_domain_rule_nftset(domain, nftsetname) != 0) {
|
||||
tlog(TLOG_ERROR, "add nftset rule failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2178,6 +2361,8 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("address", _config_address, NULL),
|
||||
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
|
||||
CONF_CUSTOM("ipset", _config_ipset, NULL),
|
||||
CONF_YESNO("nftset-timeout", &dns_conf_nftset_timeout_enable),
|
||||
CONF_CUSTOM("nftset", _config_nftset, NULL),
|
||||
CONF_CUSTOM("speed-check-mode", _config_speed_check_mode, NULL),
|
||||
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
|
||||
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
|
||||
@@ -2384,6 +2569,7 @@ static int _dns_server_load_conf_init(void)
|
||||
art_tree_init(&dns_conf_domain_rule);
|
||||
|
||||
hash_init(dns_ipset_table.ipset);
|
||||
hash_init(dns_nftset_table.nftset);
|
||||
hash_init(dns_qtype_soa_table.qtype);
|
||||
hash_init(dns_group_table.group);
|
||||
hash_init(dns_hosts_table.hosts);
|
||||
@@ -2400,6 +2586,7 @@ void dns_server_load_exit(void)
|
||||
Destroy_Radix(dns_conf_address_rule.ipv4, _config_address_destroy, NULL);
|
||||
Destroy_Radix(dns_conf_address_rule.ipv6, _config_address_destroy, NULL);
|
||||
_config_ipset_table_destroy();
|
||||
_config_nftset_table_destroy();
|
||||
_config_group_table_destroy();
|
||||
_config_ptr_table_destroy();
|
||||
_config_host_table_destroy();
|
||||
|
||||
@@ -38,6 +38,8 @@ extern "C" {
|
||||
#define DNS_MAX_SERVER_NAME_LEN 128
|
||||
#define DNS_MAX_PTR_LEN 128
|
||||
#define DNS_MAX_IPSET_NAMELEN 32
|
||||
#define DNS_MAX_NFTSET_FAMILYLEN 8
|
||||
#define DNS_MAX_NFTSET_NAMELEN 256
|
||||
#define DNS_GROUP_NAME_LEN 32
|
||||
#define DNS_NAX_GROUP_NUMBER 16
|
||||
#define DNS_MAX_IPLEN 64
|
||||
@@ -62,6 +64,8 @@ enum domain_rule {
|
||||
DOMAIN_RULE_IPSET,
|
||||
DOMAIN_RULE_IPSET_IPV4,
|
||||
DOMAIN_RULE_IPSET_IPV6,
|
||||
DOMAIN_RULE_NFTSET_IP,
|
||||
DOMAIN_RULE_NFTSET_IP6,
|
||||
DOMAIN_RULE_NAMESERVER,
|
||||
DOMAIN_RULE_CHECKSPEED,
|
||||
DOMAIN_RULE_MAX,
|
||||
@@ -90,6 +94,9 @@ typedef enum {
|
||||
#define DOMAIN_FLAG_NAMESERVER_IGNORE (1 << 9)
|
||||
#define DOMAIN_FLAG_DUALSTACK_SELECT (1 << 10)
|
||||
#define DOMAIN_FLAG_SMARTDNS_DOMAIN (1 << 11)
|
||||
#define DOMAIN_FLAG_NFTSET_INET_IGN (1 << 12)
|
||||
#define DOMAIN_FLAG_NFTSET_IP_IGN (1 << 13)
|
||||
#define DOMAIN_FLAG_NFTSET_IP6_IGN (1 << 14)
|
||||
|
||||
#define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0)
|
||||
|
||||
@@ -135,6 +142,20 @@ struct dns_ipset_rule {
|
||||
const char *ipsetname;
|
||||
};
|
||||
|
||||
struct dns_nftset_name {
|
||||
struct hlist_node node;
|
||||
char nftfamilyname[DNS_MAX_NFTSET_FAMILYLEN];
|
||||
char nfttablename[DNS_MAX_NFTSET_NAMELEN];
|
||||
char nftsetname[DNS_MAX_NFTSET_NAMELEN];
|
||||
};
|
||||
|
||||
struct dns_nftset_rule {
|
||||
struct dns_rule head;
|
||||
const char *familyname;
|
||||
const char *nfttablename;
|
||||
const char *nftsetname;
|
||||
};
|
||||
|
||||
struct dns_domain_rule {
|
||||
struct dns_rule head;
|
||||
struct dns_rule *rules[DOMAIN_RULE_MAX];
|
||||
@@ -366,6 +387,7 @@ extern int dns_conf_rr_ttl_min;
|
||||
extern int dns_conf_rr_ttl_max;
|
||||
extern int dns_conf_force_AAAA_SOA;
|
||||
extern int dns_conf_ipset_timeout_enable;
|
||||
extern int dns_conf_nftset_timeout_enable;
|
||||
extern int dns_conf_local_ttl;
|
||||
|
||||
extern int dns_conf_force_no_cname;
|
||||
|
||||
@@ -1298,7 +1298,7 @@ static int _dns_cache_reply_packet(struct dns_server_post_context *context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_setup_ipset_packet(struct dns_server_post_context *context)
|
||||
static int _dns_server_setup_ipset_nftset_packet(struct dns_server_post_context *context)
|
||||
{
|
||||
int ttl = 0;
|
||||
struct dns_request *request = context->request;
|
||||
@@ -1311,6 +1311,8 @@ static int _dns_server_setup_ipset_packet(struct dns_server_post_context *contex
|
||||
struct dns_ipset_rule *ipset_rule = NULL;
|
||||
struct dns_ipset_rule *ipset_rule_v4 = NULL;
|
||||
struct dns_ipset_rule *ipset_rule_v6 = NULL;
|
||||
struct dns_nftset_rule *nftset_ip = NULL;
|
||||
struct dns_nftset_rule *nftset_ip6 = NULL;
|
||||
struct dns_rule_flags *rule_flags = NULL;
|
||||
|
||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_IPSET) == 0) {
|
||||
@@ -1336,8 +1338,14 @@ static int _dns_server_setup_ipset_packet(struct dns_server_post_context *contex
|
||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_IPSET_IPV6_IGN) == 0) {
|
||||
ipset_rule_v6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_IPSET_IPV6);
|
||||
}
|
||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_NFTSET_IP_IGN) == 0) {
|
||||
nftset_ip = _dns_server_get_dns_rule(request, DOMAIN_RULE_NFTSET_IP);
|
||||
}
|
||||
if (!rule_flags || (rule_flags->flags & DOMAIN_FLAG_NFTSET_IP6_IGN) == 0) {
|
||||
nftset_ip6 = _dns_server_get_dns_rule(request, DOMAIN_RULE_NFTSET_IP6);
|
||||
}
|
||||
|
||||
if (!(ipset_rule || ipset_rule_v4 || ipset_rule_v6)) {
|
||||
if (!(ipset_rule || ipset_rule_v4 || ipset_rule_v6 || nftset_ip || nftset_ip6)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1354,14 +1362,23 @@ static int _dns_server_setup_ipset_packet(struct dns_server_post_context *contex
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
rule = ipset_rule_v4 ? ipset_rule_v4 : ipset_rule;
|
||||
if (rule == NULL) {
|
||||
break;
|
||||
if (rule != NULL) {
|
||||
/* add IPV4 to ipset */
|
||||
ipset_add(rule->ipsetname, addr, DNS_RR_A_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG, "IPSET-MATCH: domain: %s, ipset: %s, IP: %d.%d.%d.%d", request->domain,
|
||||
rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
|
||||
}
|
||||
|
||||
/* add IPV4 to ipset */
|
||||
ipset_add(rule->ipsetname, addr, DNS_RR_A_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG, "IPSET-MATCH: domain: %s, ipset: %s, IP: %d.%d.%d.%d", request->domain,
|
||||
rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
|
||||
#ifdef WITH_NFTSET
|
||||
if (nftset_ip != NULL) {
|
||||
/* add IPV4 to ipset */
|
||||
nftset_add(nftset_ip->familyname, nftset_ip->nfttablename, nftset_ip->nftsetname, addr,
|
||||
DNS_RR_A_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG, "NFTSET-MATCH: domain: %s, nftset: %s %s %s, IP: %d.%d.%d.%d", request->domain,
|
||||
nftset_ip->familyname, nftset_ip->nfttablename, nftset_ip->nftsetname, addr[0], addr[1],
|
||||
addr[2], addr[3]);
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
@@ -1372,16 +1389,28 @@ static int _dns_server_setup_ipset_packet(struct dns_server_post_context *contex
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
rule = ipset_rule_v6 ? ipset_rule_v6 : ipset_rule;
|
||||
if (rule == NULL) {
|
||||
break;
|
||||
if (rule != NULL) {
|
||||
ipset_add(rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG,
|
||||
"IPSET-MATCH: domain: %s, ipset: %s, IP: "
|
||||
"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
|
||||
addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14],
|
||||
addr[15]);
|
||||
}
|
||||
|
||||
ipset_add(rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG,
|
||||
"IPSET-MATCH: domain: %s, ipset: %s, IP: "
|
||||
"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6],
|
||||
addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
#ifdef WITH_NFTSET
|
||||
if (nftset_ip6 != NULL) {
|
||||
/* add IPV6 to ipset */
|
||||
nftset_add(nftset_ip6->familyname, nftset_ip6->nfttablename, nftset_ip6->nftsetname, addr,
|
||||
DNS_RR_AAAA_LEN, request->ip_ttl * 2);
|
||||
tlog(TLOG_DEBUG,
|
||||
"NFTSET-MATCH: domain: %s, nftset: %s %s %s, IP: "
|
||||
"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, nftset_ip6->familyname, nftset_ip6->nfttablename, nftset_ip6->nftsetname,
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
|
||||
addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
@@ -1420,7 +1449,7 @@ static int _dns_request_post(struct dns_server_post_context *context)
|
||||
}
|
||||
|
||||
/* setup ipset */
|
||||
_dns_server_setup_ipset_packet(context);
|
||||
_dns_server_setup_ipset_nftset_packet(context);
|
||||
|
||||
if (context->do_reply == 0) {
|
||||
return 0;
|
||||
@@ -2769,7 +2798,7 @@ static int _dns_server_reply_passthrouth(struct dns_server_post_context *context
|
||||
|
||||
_dns_cache_reply_packet(context);
|
||||
|
||||
if (_dns_server_setup_ipset_packet(context) != 0) {
|
||||
if (_dns_server_setup_ipset_nftset_packet(context) != 0) {
|
||||
tlog(TLOG_DEBUG, "setup ipset failed.");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GENERIC_HASH_H
|
||||
#define _GENERIC_HASH_H
|
||||
|
||||
@@ -30,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef BITS_PER_LONG
|
||||
# define BITS_PER_LONG __WORDSIZE
|
||||
#define BITS_PER_LONG __WORDSIZE
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -39,14 +38,12 @@
|
||||
* more efficiently than using fls() and fls64()
|
||||
* - the arch is not required to handle n==0 if implementing the fallback
|
||||
*/
|
||||
static inline __attribute__((const))
|
||||
int __ilog2_u32(uint32_t n)
|
||||
static inline __attribute__((const)) int __ilog2_u32(uint32_t n)
|
||||
{
|
||||
return fls(n) - 1;
|
||||
}
|
||||
|
||||
static inline __attribute__((const))
|
||||
int __ilog2_u64(uint64_t n)
|
||||
static inline __attribute__((const)) int __ilog2_u64(uint64_t n)
|
||||
{
|
||||
return fls64(n) - 1;
|
||||
}
|
||||
@@ -61,78 +58,73 @@ int __ilog2_u64(uint64_t n)
|
||||
*
|
||||
* selects the appropriately-sized optimised version depending on sizeof(n)
|
||||
*/
|
||||
#define ilog2(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
(n) < 2 ? 0 : \
|
||||
(n) & (1ULL << 63) ? 63 : \
|
||||
(n) & (1ULL << 62) ? 62 : \
|
||||
(n) & (1ULL << 61) ? 61 : \
|
||||
(n) & (1ULL << 60) ? 60 : \
|
||||
(n) & (1ULL << 59) ? 59 : \
|
||||
(n) & (1ULL << 58) ? 58 : \
|
||||
(n) & (1ULL << 57) ? 57 : \
|
||||
(n) & (1ULL << 56) ? 56 : \
|
||||
(n) & (1ULL << 55) ? 55 : \
|
||||
(n) & (1ULL << 54) ? 54 : \
|
||||
(n) & (1ULL << 53) ? 53 : \
|
||||
(n) & (1ULL << 52) ? 52 : \
|
||||
(n) & (1ULL << 51) ? 51 : \
|
||||
(n) & (1ULL << 50) ? 50 : \
|
||||
(n) & (1ULL << 49) ? 49 : \
|
||||
(n) & (1ULL << 48) ? 48 : \
|
||||
(n) & (1ULL << 47) ? 47 : \
|
||||
(n) & (1ULL << 46) ? 46 : \
|
||||
(n) & (1ULL << 45) ? 45 : \
|
||||
(n) & (1ULL << 44) ? 44 : \
|
||||
(n) & (1ULL << 43) ? 43 : \
|
||||
(n) & (1ULL << 42) ? 42 : \
|
||||
(n) & (1ULL << 41) ? 41 : \
|
||||
(n) & (1ULL << 40) ? 40 : \
|
||||
(n) & (1ULL << 39) ? 39 : \
|
||||
(n) & (1ULL << 38) ? 38 : \
|
||||
(n) & (1ULL << 37) ? 37 : \
|
||||
(n) & (1ULL << 36) ? 36 : \
|
||||
(n) & (1ULL << 35) ? 35 : \
|
||||
(n) & (1ULL << 34) ? 34 : \
|
||||
(n) & (1ULL << 33) ? 33 : \
|
||||
(n) & (1ULL << 32) ? 32 : \
|
||||
(n) & (1ULL << 31) ? 31 : \
|
||||
(n) & (1ULL << 30) ? 30 : \
|
||||
(n) & (1ULL << 29) ? 29 : \
|
||||
(n) & (1ULL << 28) ? 28 : \
|
||||
(n) & (1ULL << 27) ? 27 : \
|
||||
(n) & (1ULL << 26) ? 26 : \
|
||||
(n) & (1ULL << 25) ? 25 : \
|
||||
(n) & (1ULL << 24) ? 24 : \
|
||||
(n) & (1ULL << 23) ? 23 : \
|
||||
(n) & (1ULL << 22) ? 22 : \
|
||||
(n) & (1ULL << 21) ? 21 : \
|
||||
(n) & (1ULL << 20) ? 20 : \
|
||||
(n) & (1ULL << 19) ? 19 : \
|
||||
(n) & (1ULL << 18) ? 18 : \
|
||||
(n) & (1ULL << 17) ? 17 : \
|
||||
(n) & (1ULL << 16) ? 16 : \
|
||||
(n) & (1ULL << 15) ? 15 : \
|
||||
(n) & (1ULL << 14) ? 14 : \
|
||||
(n) & (1ULL << 13) ? 13 : \
|
||||
(n) & (1ULL << 12) ? 12 : \
|
||||
(n) & (1ULL << 11) ? 11 : \
|
||||
(n) & (1ULL << 10) ? 10 : \
|
||||
(n) & (1ULL << 9) ? 9 : \
|
||||
(n) & (1ULL << 8) ? 8 : \
|
||||
(n) & (1ULL << 7) ? 7 : \
|
||||
(n) & (1ULL << 6) ? 6 : \
|
||||
(n) & (1ULL << 5) ? 5 : \
|
||||
(n) & (1ULL << 4) ? 4 : \
|
||||
(n) & (1ULL << 3) ? 3 : \
|
||||
(n) & (1ULL << 2) ? 2 : \
|
||||
1 ) : \
|
||||
(sizeof(n) <= 4) ? \
|
||||
__ilog2_u32(n) : \
|
||||
__ilog2_u64(n) \
|
||||
)
|
||||
|
||||
#define ilog2(n) \
|
||||
(__builtin_constant_p(n) ? ((n) < 2 ? 0 \
|
||||
: (n) & (1ULL << 63) ? 63 \
|
||||
: (n) & (1ULL << 62) ? 62 \
|
||||
: (n) & (1ULL << 61) ? 61 \
|
||||
: (n) & (1ULL << 60) ? 60 \
|
||||
: (n) & (1ULL << 59) ? 59 \
|
||||
: (n) & (1ULL << 58) ? 58 \
|
||||
: (n) & (1ULL << 57) ? 57 \
|
||||
: (n) & (1ULL << 56) ? 56 \
|
||||
: (n) & (1ULL << 55) ? 55 \
|
||||
: (n) & (1ULL << 54) ? 54 \
|
||||
: (n) & (1ULL << 53) ? 53 \
|
||||
: (n) & (1ULL << 52) ? 52 \
|
||||
: (n) & (1ULL << 51) ? 51 \
|
||||
: (n) & (1ULL << 50) ? 50 \
|
||||
: (n) & (1ULL << 49) ? 49 \
|
||||
: (n) & (1ULL << 48) ? 48 \
|
||||
: (n) & (1ULL << 47) ? 47 \
|
||||
: (n) & (1ULL << 46) ? 46 \
|
||||
: (n) & (1ULL << 45) ? 45 \
|
||||
: (n) & (1ULL << 44) ? 44 \
|
||||
: (n) & (1ULL << 43) ? 43 \
|
||||
: (n) & (1ULL << 42) ? 42 \
|
||||
: (n) & (1ULL << 41) ? 41 \
|
||||
: (n) & (1ULL << 40) ? 40 \
|
||||
: (n) & (1ULL << 39) ? 39 \
|
||||
: (n) & (1ULL << 38) ? 38 \
|
||||
: (n) & (1ULL << 37) ? 37 \
|
||||
: (n) & (1ULL << 36) ? 36 \
|
||||
: (n) & (1ULL << 35) ? 35 \
|
||||
: (n) & (1ULL << 34) ? 34 \
|
||||
: (n) & (1ULL << 33) ? 33 \
|
||||
: (n) & (1ULL << 32) ? 32 \
|
||||
: (n) & (1ULL << 31) ? 31 \
|
||||
: (n) & (1ULL << 30) ? 30 \
|
||||
: (n) & (1ULL << 29) ? 29 \
|
||||
: (n) & (1ULL << 28) ? 28 \
|
||||
: (n) & (1ULL << 27) ? 27 \
|
||||
: (n) & (1ULL << 26) ? 26 \
|
||||
: (n) & (1ULL << 25) ? 25 \
|
||||
: (n) & (1ULL << 24) ? 24 \
|
||||
: (n) & (1ULL << 23) ? 23 \
|
||||
: (n) & (1ULL << 22) ? 22 \
|
||||
: (n) & (1ULL << 21) ? 21 \
|
||||
: (n) & (1ULL << 20) ? 20 \
|
||||
: (n) & (1ULL << 19) ? 19 \
|
||||
: (n) & (1ULL << 18) ? 18 \
|
||||
: (n) & (1ULL << 17) ? 17 \
|
||||
: (n) & (1ULL << 16) ? 16 \
|
||||
: (n) & (1ULL << 15) ? 15 \
|
||||
: (n) & (1ULL << 14) ? 14 \
|
||||
: (n) & (1ULL << 13) ? 13 \
|
||||
: (n) & (1ULL << 12) ? 12 \
|
||||
: (n) & (1ULL << 11) ? 11 \
|
||||
: (n) & (1ULL << 10) ? 10 \
|
||||
: (n) & (1ULL << 9) ? 9 \
|
||||
: (n) & (1ULL << 8) ? 8 \
|
||||
: (n) & (1ULL << 7) ? 7 \
|
||||
: (n) & (1ULL << 6) ? 6 \
|
||||
: (n) & (1ULL << 5) ? 5 \
|
||||
: (n) & (1ULL << 4) ? 4 \
|
||||
: (n) & (1ULL << 3) ? 3 \
|
||||
: (n) & (1ULL << 2) ? 2 \
|
||||
: 1) \
|
||||
: (sizeof(n) <= 4) ? __ilog2_u32(n) \
|
||||
: __ilog2_u64(n))
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
|
||||
@@ -221,14 +213,29 @@ static inline uint32_t hash32_ptr(const void *ptr)
|
||||
|
||||
static inline uint32_t hash_string(const char *s)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
uint32_t h = 0;
|
||||
|
||||
while (*s) {
|
||||
h = h * 31 + *s;
|
||||
s++;
|
||||
}
|
||||
while (*s) {
|
||||
h = h * 31 + *s;
|
||||
s++;
|
||||
}
|
||||
|
||||
return h;
|
||||
return h;
|
||||
}
|
||||
|
||||
static inline uint32_t hash_string_array(const char **a)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
|
||||
const char *s;
|
||||
while ((s = *a++)) {
|
||||
while (*s) {
|
||||
h = h * 31 + *s;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
#endif /* _GENERIC_HASH_H */
|
||||
|
||||
71
src/util.c
71
src/util.c
@@ -18,10 +18,11 @@
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "util.h"
|
||||
#include "dns_conf.h"
|
||||
#include "tlog.h"
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
@@ -46,6 +47,10 @@
|
||||
#include <unistd.h>
|
||||
#include <unwind.h>
|
||||
|
||||
#ifdef WITH_NFTSET
|
||||
#include <nftables/libnftables.h>
|
||||
#endif
|
||||
|
||||
#define TMP_BUFF_LEN_32 32
|
||||
|
||||
#define NFNL_SUBSYS_IPSET 6
|
||||
@@ -636,6 +641,70 @@ int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len)
|
||||
return _ipset_operate(ipsetname, addr, addr_len, 0, IPSET_DEL);
|
||||
}
|
||||
|
||||
#ifdef WITH_NFTSET
|
||||
static struct nft_ctx *_nftset_init(void)
|
||||
{
|
||||
static struct nft_ctx *nft_ctx = NULL;
|
||||
if (nft_ctx) {
|
||||
return nft_ctx;
|
||||
}
|
||||
|
||||
nft_ctx = nft_ctx_new(NFT_CTX_DEFAULT);
|
||||
if (!nft_ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nft_ctx_buffer_error(nft_ctx);
|
||||
return nft_ctx;
|
||||
}
|
||||
|
||||
static int _nftset_operate(const char *familyname, const char *tablename, const char *setname,
|
||||
const unsigned char addr[], int af, const char *op, const char *flags)
|
||||
{
|
||||
char cmd_buf[1024] = {'\0'};
|
||||
|
||||
struct nft_ctx *nft_ctx = _nftset_init();
|
||||
if (nft_ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char addr_str[INET6_ADDRSTRLEN];
|
||||
if (!inet_ntop(af, addr, addr_str, INET6_ADDRSTRLEN)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = snprintf(cmd_buf, sizeof(cmd_buf), "%s element %s %s %s { %s %s }", op, familyname, tablename, setname,
|
||||
addr_str, flags);
|
||||
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = nft_run_cmd_from_buffer(nft_ctx, cmd_buf);
|
||||
nft_ctx_get_error_buffer(nft_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nftset_add(const char *familyname, const char *tablename, const char *setname, const unsigned char addr[],
|
||||
int addr_len, unsigned long timeout)
|
||||
{
|
||||
char flag_timeout[32] = {'\0'};
|
||||
int af = addr_len == IPV6_ADDR_LEN ? AF_INET6 : AF_INET;
|
||||
if (dns_conf_nftset_timeout_enable) {
|
||||
snprintf(flag_timeout, sizeof(flag_timeout), "timeout %lus", timeout);
|
||||
}
|
||||
return _nftset_operate(familyname, tablename, setname, addr, af, "add", flag_timeout);
|
||||
}
|
||||
|
||||
int nftset_del(const char *familyname, const char *tablename, const char *setname, const unsigned char addr[],
|
||||
int addr_len)
|
||||
{
|
||||
int af = addr_len == IPV6_ADDR_LEN ? AF_INET6 : AF_INET;
|
||||
return _nftset_operate(familyname, tablename, setname, addr, af, "delete", "");
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char *SSL_SHA256(const unsigned char *d, size_t n, unsigned char *md)
|
||||
{
|
||||
static unsigned char m[SHA256_DIGEST_LENGTH];
|
||||
|
||||
12
src/util.h
12
src/util.h
@@ -46,9 +46,7 @@ extern "C" {
|
||||
#define MAX_IP_LEN 64
|
||||
|
||||
#ifndef BASE_FILE_NAME
|
||||
#define BASE_FILE_NAME \
|
||||
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
|
||||
: __FILE__)
|
||||
#define BASE_FILE_NAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
#endif
|
||||
#define BUG(format, ...) bug_ext(BASE_FILE_NAME, __LINE__, __func__, format, ##__VA_ARGS__)
|
||||
|
||||
@@ -83,6 +81,14 @@ int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len, u
|
||||
|
||||
int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len);
|
||||
|
||||
#ifdef WITH_NFTSET
|
||||
int nftset_add(const char *familyname, const char *tablename, const char *setname, const unsigned char addr[],
|
||||
int addr_len, unsigned long timeout);
|
||||
|
||||
int nftset_del(const char *faimlyname, const char *tablename, const char *setname, const unsigned char addr[],
|
||||
int addr_len);
|
||||
#endif
|
||||
|
||||
void SSL_CRYPTO_thread_setup(void);
|
||||
|
||||
void SSL_CRYPTO_thread_cleanup(void);
|
||||
|
||||
Reference in New Issue
Block a user