mirror of
https://github.com/status-im/miniupnp.git
synced 2025-01-18 18:31:15 +00:00
establish persistent mnl/netlink socket at init_redirect (needs elevated privileges)
This commit is contained in:
parent
22223da9a1
commit
123e589266
@ -66,11 +66,17 @@ static struct timestamp_entry * timestamp_list = NULL;
|
||||
|
||||
/* init and shutdown functions */
|
||||
int
|
||||
init_redirect(void) {
|
||||
init_redirect(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* requires elevated privileges */
|
||||
result = nft_mnl_connect();
|
||||
|
||||
/* 'inet' family */
|
||||
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_INET, nft_table);
|
||||
if (result == 0) {
|
||||
result = table_op(NFT_MSG_NEWTABLE, NFPROTO_INET, nft_table);
|
||||
}
|
||||
if (result == 0) {
|
||||
result = chain_op(NFT_MSG_NEWCHAIN, NFPROTO_INET, nft_table,
|
||||
nft_forward_chain, FILTER_CHAIN_TYPE, NF_INET_FORWARD, NF_IP_PRI_FILTER - 25);
|
||||
@ -140,7 +146,7 @@ shutdown_redirect(void) {
|
||||
result = table_op(NFT_MSG_DELTABLE, NFPROTO_IPV6, nft_table);
|
||||
}
|
||||
|
||||
finish_batch();
|
||||
nft_mnl_disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,8 +68,9 @@ const char * nft_prerouting_chain = "prerouting";
|
||||
const char * nft_postrouting_chain = "postrouting";
|
||||
const char * nft_forward_chain = "forward";
|
||||
|
||||
static struct mnl_socket *nl = NULL;
|
||||
static uint32_t nl_seq = 0;
|
||||
static struct mnl_socket *mnl_sock = NULL;
|
||||
static uint32_t mnl_portid = 0;
|
||||
static uint32_t mnl_seq = 0;
|
||||
|
||||
// FILTER
|
||||
struct rule_list head_filter = LIST_HEAD_INITIALIZER(head_filter);
|
||||
@ -82,6 +83,34 @@ static uint32_t rule_list_filter_validate = RULE_CACHE_INVALID;
|
||||
static uint32_t rule_list_redirect_validate = RULE_CACHE_INVALID;
|
||||
static uint32_t rule_list_peer_validate = RULE_CACHE_INVALID;
|
||||
|
||||
|
||||
int
|
||||
nft_mnl_connect(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
mnl_sock = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (mnl_sock == NULL) {
|
||||
log_error("mnl_socket_open() FAILED: %m");
|
||||
result = errno;
|
||||
} else {
|
||||
if (mnl_socket_bind(mnl_sock, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
log_error("mnl_socket_bind() FAILED: %m");
|
||||
result = errno;
|
||||
} else {
|
||||
mnl_portid = mnl_socket_get_portid(mnl_sock);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nft_mnl_disconnect(void)
|
||||
{
|
||||
mnl_socket_close(mnl_sock);
|
||||
mnl_sock = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *
|
||||
get_family_string(uint32_t family)
|
||||
@ -706,59 +735,44 @@ refresh_nft_cache(struct rule_list *head, const char *table, const char *chain,
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
uint32_t portid, seq, type = NFTNL_OUTPUT_DEFAULT;
|
||||
struct nftnl_rule *t;
|
||||
uint32_t type = NFTNL_OUTPUT_DEFAULT;
|
||||
struct nftnl_rule *rule;
|
||||
int ret;
|
||||
|
||||
flush_nft_cache(head);
|
||||
|
||||
if (nl == NULL) {
|
||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (nl == NULL) {
|
||||
log_error("mnl_socket_open() FAILED: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
log_error("mnl_socket_bind() FAILED: %m");
|
||||
return;
|
||||
}
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
t = nftnl_rule_alloc();
|
||||
if (t == NULL) {
|
||||
rule = nftnl_rule_alloc();
|
||||
if (rule == NULL) {
|
||||
log_error("nftnl_rule_alloc() FAILED");
|
||||
return;
|
||||
}
|
||||
|
||||
seq = time(NULL);
|
||||
mnl_seq = time(NULL);
|
||||
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family,
|
||||
NLM_F_DUMP, seq);
|
||||
nftnl_rule_set(t, NFTNL_RULE_TABLE, table);
|
||||
nftnl_rule_set(t, NFTNL_RULE_CHAIN, chain);
|
||||
nftnl_rule_nlmsg_build_payload(nlh, t);
|
||||
nftnl_rule_free(t);
|
||||
NLM_F_DUMP, mnl_seq);
|
||||
nftnl_rule_set(rule, NFTNL_RULE_TABLE, table);
|
||||
nftnl_rule_set(rule, NFTNL_RULE_CHAIN, chain);
|
||||
nftnl_rule_nlmsg_build_payload(nlh, rule);
|
||||
nftnl_rule_free(rule);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
if (mnl_socket_sendto(mnl_sock, nlh, nlh->nlmsg_len) < 0) {
|
||||
log_error("mnl_socket_sendto() FAILED: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
ret = mnl_socket_recvfrom(mnl_sock, buf, sizeof(buf));
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, table_cb, &type);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
ret = mnl_cb_run(buf, ret, mnl_seq, mnl_portid, table_cb, &type);
|
||||
if (ret > 0)
|
||||
{
|
||||
ret = mnl_socket_recvfrom(mnl_sock, buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
log_error("mnl_socket_recvfrom() FAILED: %m");
|
||||
}
|
||||
|
||||
/* mnl_socket_close(nl); */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1287,7 +1301,7 @@ nft_send_rule(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type chain
|
||||
cmd,
|
||||
nftnl_rule_get_u32(rule, NFTNL_RULE_FAMILY),
|
||||
NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK,
|
||||
nl_seq++);
|
||||
mnl_seq++);
|
||||
|
||||
nftnl_rule_nlmsg_build_payload(nlh, rule);
|
||||
nftnl_rule_free(rule);
|
||||
@ -1326,7 +1340,7 @@ table_op( enum nf_tables_msg_types op, uint16_t family, const char * name)
|
||||
nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
||||
op, family,
|
||||
(op == NFT_MSG_NEWTABLE ? NLM_F_CREATE : 0) | NLM_F_ACK,
|
||||
nl_seq++);
|
||||
mnl_seq++);
|
||||
nftnl_table_nlmsg_build_payload(nlh, table);
|
||||
|
||||
result = send_batch(batch);
|
||||
@ -1371,7 +1385,7 @@ chain_op(enum nf_tables_msg_types op, uint16_t family, const char * table,
|
||||
nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
|
||||
op, family,
|
||||
(op == NFT_MSG_NEWCHAIN ? NLM_F_CREATE : 0) | NLM_F_ACK,
|
||||
nl_seq++);
|
||||
mnl_seq++);
|
||||
if (nlh == NULL)
|
||||
{
|
||||
log_error("failed to build header: %m");
|
||||
@ -1391,77 +1405,61 @@ chain_op(enum nf_tables_msg_types op, uint16_t family, const char * table,
|
||||
struct mnl_nlmsg_batch *
|
||||
start_batch( char *buf, size_t buf_size)
|
||||
{
|
||||
struct mnl_nlmsg_batch *batch;
|
||||
nl_seq = time(NULL);
|
||||
struct mnl_nlmsg_batch *result;
|
||||
mnl_seq = time(NULL);
|
||||
|
||||
if (nl == NULL) {
|
||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (nl == NULL) {
|
||||
log_error("mnl_socket_open() FAILED: %m");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
log_error("mnl_socket_bind() FAILED: %m");
|
||||
return NULL;
|
||||
}
|
||||
if (mnl_sock == NULL) {
|
||||
log_error("netlink not connected");
|
||||
result = NULL;
|
||||
} else {
|
||||
result = mnl_nlmsg_batch_start(buf, buf_size);
|
||||
if (result != NULL) {
|
||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(result),
|
||||
NFNL_MSG_BATCH_BEGIN, mnl_seq++);
|
||||
mnl_nlmsg_batch_next(result);
|
||||
}
|
||||
}
|
||||
|
||||
batch = mnl_nlmsg_batch_start(buf, buf_size);
|
||||
if (batch != NULL) {
|
||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch),
|
||||
NFNL_MSG_BATCH_BEGIN, nl_seq++);
|
||||
mnl_nlmsg_batch_next(batch);
|
||||
}
|
||||
return batch;
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
send_batch(struct mnl_nlmsg_batch * batch)
|
||||
send_batch(struct mnl_nlmsg_batch *batch)
|
||||
{
|
||||
int ret;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
int ret;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
|
||||
mnl_nlmsg_batch_next(batch);
|
||||
mnl_nlmsg_batch_next(batch);
|
||||
|
||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END,
|
||||
nl_seq++);
|
||||
mnl_nlmsg_batch_next(batch);
|
||||
nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, mnl_seq++);
|
||||
mnl_nlmsg_batch_next(batch);
|
||||
|
||||
if (nl == NULL) {
|
||||
log_error("netlink not connected");
|
||||
return -1;
|
||||
} else {
|
||||
ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch),
|
||||
mnl_nlmsg_batch_size(batch));
|
||||
if (ret == -1) {
|
||||
log_error("mnl_socket_sendto() FAILED: %m");
|
||||
return -2;
|
||||
}
|
||||
if (mnl_sock == NULL) {
|
||||
log_error("netlink not connected");
|
||||
return -1;
|
||||
} else {
|
||||
ret = mnl_socket_sendto(mnl_sock, mnl_nlmsg_batch_head(batch),
|
||||
mnl_nlmsg_batch_size(batch));
|
||||
if (ret == -1) {
|
||||
log_error("mnl_socket_sendto() FAILED: %m");
|
||||
return -2;
|
||||
} else {
|
||||
mnl_nlmsg_batch_stop(batch);
|
||||
|
||||
mnl_nlmsg_batch_stop(batch);
|
||||
|
||||
do {
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret == -1) {
|
||||
log_error("mnl_socket_recvfrom() FAILED: %m");
|
||||
return -3;
|
||||
} else if (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL);
|
||||
do {
|
||||
ret = mnl_socket_recvfrom(mnl_sock, buf, sizeof(buf));
|
||||
if (ret == -1) {
|
||||
log_error("mnl_cb_run() FAILED: %m");
|
||||
return -4;
|
||||
log_error("mnl_socket_recvfrom() FAILED: %m");
|
||||
return -3;
|
||||
} else if (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, 0, mnl_portid, NULL, NULL);
|
||||
if (ret == -1) {
|
||||
log_error("mnl_cb_run() FAILED: %m");
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (ret > 0);
|
||||
}
|
||||
/* mnl_socket_close(nl); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
finish_batch(void)
|
||||
{
|
||||
mnl_socket_close(nl);
|
||||
nl = NULL;
|
||||
} while (ret > 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -83,6 +83,15 @@ extern struct rule_list head_filter;
|
||||
extern struct rule_list head_redirect;
|
||||
extern struct rule_list head_peer;
|
||||
|
||||
/** called at initialization.
|
||||
* establishes persistent connection to mnl/netfilter socket, needs elevated privilege */
|
||||
int
|
||||
nft_mnl_connect(void);
|
||||
|
||||
/** called at shutdown, to release the mnl/netfilter socket */
|
||||
void
|
||||
nft_mnl_disconnect(void);
|
||||
|
||||
int
|
||||
nft_send_rule(struct nftnl_rule * rule, uint16_t cmd, enum rule_chain_type type);
|
||||
struct nftnl_rule *
|
||||
@ -129,5 +138,3 @@ struct mnl_nlmsg_batch *
|
||||
start_batch( char *buf, size_t buf_size);
|
||||
int
|
||||
send_batch(struct mnl_nlmsg_batch * batch);
|
||||
void
|
||||
finish_batch(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user