|
Packit Service |
1ec7f4 |
/*
|
|
Packit Service |
1ec7f4 |
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit Service |
1ec7f4 |
*
|
|
Packit Service |
1ec7f4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
1ec7f4 |
* it under the terms of the GNU General Public License as published
|
|
Packit Service |
1ec7f4 |
* by the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
1ec7f4 |
* (at your option) any later version.
|
|
Packit Service |
1ec7f4 |
*
|
|
Packit Service |
1ec7f4 |
* This code has been sponsored by Sophos Astaro <http://www.sophos.com>
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <unistd.h>
|
|
Packit Service |
1ec7f4 |
#include <fcntl.h>
|
|
Packit Service |
1ec7f4 |
#include <sys/types.h>
|
|
Packit Service |
1ec7f4 |
#include <sys/socket.h>
|
|
Packit Service |
1ec7f4 |
#include <stdbool.h>
|
|
Packit Service |
1ec7f4 |
#include <errno.h>
|
|
Packit Service |
1ec7f4 |
#include <netdb.h> /* getprotobynumber */
|
|
Packit Service |
1ec7f4 |
#include <time.h>
|
|
Packit Service |
1ec7f4 |
#include <stdarg.h>
|
|
Packit Service |
1ec7f4 |
#include <inttypes.h>
|
|
Packit Service |
1ec7f4 |
#include <assert.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <xtables.h>
|
|
Packit Service |
1ec7f4 |
#include <libiptc/libxtc.h>
|
|
Packit Service |
1ec7f4 |
#include <libiptc/xtcshared.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <stdlib.h>
|
|
Packit Service |
1ec7f4 |
#include <string.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter/x_tables.h>
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter_ipv4/ip_tables.h>
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter_ipv6/ip6_tables.h>
|
|
Packit Service |
1ec7f4 |
#include <netinet/ip6.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <linux/netlink.h>
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter/nfnetlink.h>
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter/nf_tables.h>
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter/nf_tables_compat.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter/xt_limit.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <libmnl/libmnl.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/table.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/chain.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/rule.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/expr.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/set.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/udata.h>
|
|
Packit Service |
1ec7f4 |
#include <libnftnl/batch.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <netinet/in.h> /* inet_ntoa */
|
|
Packit Service |
1ec7f4 |
#include <arpa/inet.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include "nft.h"
|
|
Packit Service |
1ec7f4 |
#include "xshared.h" /* proto_to_name */
|
|
Packit Service |
1ec7f4 |
#include "nft-shared.h"
|
|
Packit Service |
1ec7f4 |
#include "xtables-config-parser.h"
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void *nft_fn;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
|
|
Packit Service |
1ec7f4 |
int (*cb)(const struct nlmsghdr *nlh, void *data),
|
|
Packit Service |
1ec7f4 |
void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
char buf[16536];
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
|
|
Packit Service |
1ec7f4 |
while (ret > 0) {
|
|
Packit Service |
1ec7f4 |
ret = mnl_cb_run(buf, ret, h->seq, h->portid, cb, data);
|
|
Packit Service |
1ec7f4 |
if (ret <= 0)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
if (ret == -1) {
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#define NFT_NLMSG_MAXSIZE (UINT16_MAX + getpagesize())
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* selected batch page is 256 Kbytes long to load ruleset of
|
|
Packit Service |
1ec7f4 |
* half a million rules without hitting -EMSGSIZE due to large
|
|
Packit Service |
1ec7f4 |
* iovec.
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
#define BATCH_PAGE_SIZE getpagesize() * 32
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_batch *mnl_batch_init(void)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_batch *batch;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
batch = nftnl_batch_alloc(BATCH_PAGE_SIZE, NFT_NLMSG_MAXSIZE);
|
|
Packit Service |
1ec7f4 |
if (batch == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return batch;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_nft_batch_continue(struct nftnl_batch *batch)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
assert(nftnl_batch_update(batch) >= 0);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static uint32_t mnl_batch_begin(struct nftnl_batch *batch, uint32_t seqnum)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nftnl_batch_begin(nftnl_batch_buffer(batch), seqnum);
|
|
Packit Service |
1ec7f4 |
mnl_nft_batch_continue(batch);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return seqnum;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_batch_end(struct nftnl_batch *batch, uint32_t seqnum)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nftnl_batch_end(nftnl_batch_buffer(batch), seqnum);
|
|
Packit Service |
1ec7f4 |
mnl_nft_batch_continue(batch);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_batch_reset(struct nftnl_batch *batch)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nftnl_batch_free(batch);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct mnl_err {
|
|
Packit Service |
1ec7f4 |
struct list_head head;
|
|
Packit Service |
1ec7f4 |
int err;
|
|
Packit Service |
1ec7f4 |
uint32_t seqnum;
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_err_list_node_add(struct list_head *err_list, int error,
|
|
Packit Service |
1ec7f4 |
int seqnum)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct mnl_err *err = malloc(sizeof(struct mnl_err));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err->seqnum = seqnum;
|
|
Packit Service |
1ec7f4 |
err->err = error;
|
|
Packit Service |
1ec7f4 |
list_add_tail(&err->head, err_list);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_err_list_free(struct mnl_err *err)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
list_del(&err->head);
|
|
Packit Service |
1ec7f4 |
free(err);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nlbuffsiz;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void mnl_set_sndbuffer(const struct mnl_socket *nl,
|
|
Packit Service |
1ec7f4 |
struct nftnl_batch *batch)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int newbuffsiz;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
newbuffsiz = nftnl_batch_iovec_len(batch) * BATCH_PAGE_SIZE;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Rise sender buffer length to avoid hitting -EMSGSIZE */
|
|
Packit Service |
1ec7f4 |
if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUFFORCE,
|
|
Packit Service |
1ec7f4 |
&newbuffsiz, sizeof(socklen_t)) < 0)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlbuffsiz = newbuffsiz;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock,
|
|
Packit Service |
1ec7f4 |
struct nftnl_batch *batch)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
static const struct sockaddr_nl snl = {
|
|
Packit Service |
1ec7f4 |
.nl_family = AF_NETLINK
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
uint32_t iov_len = nftnl_batch_iovec_len(batch);
|
|
Packit Service |
1ec7f4 |
struct iovec iov[iov_len];
|
|
Packit Service |
1ec7f4 |
struct msghdr msg = {
|
|
Packit Service |
1ec7f4 |
.msg_name = (struct sockaddr *) &snl,
|
|
Packit Service |
1ec7f4 |
.msg_namelen = sizeof(snl),
|
|
Packit Service |
1ec7f4 |
.msg_iov = iov,
|
|
Packit Service |
1ec7f4 |
.msg_iovlen = iov_len,
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
mnl_set_sndbuffer(nf_sock, batch);
|
|
Packit Service |
1ec7f4 |
nftnl_batch_iovec(batch, iov, iov_len);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return sendmsg(mnl_socket_get_fd(nf_sock), &msg, 0);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int mnl_batch_talk(const struct mnl_socket *nf_sock,
|
|
Packit Service |
1ec7f4 |
struct nftnl_batch *batch, struct list_head *err_list)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const struct mnl_socket *nl = nf_sock;
|
|
Packit Service |
1ec7f4 |
int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl);
|
|
Packit Service |
1ec7f4 |
char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
|
|
Packit Service |
1ec7f4 |
fd_set readfds;
|
|
Packit Service |
1ec7f4 |
struct timeval tv = {
|
|
Packit Service |
1ec7f4 |
.tv_sec = 0,
|
|
Packit Service |
1ec7f4 |
.tv_usec = 0
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
int err = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_nft_socket_sendmsg(nf_sock, batch);
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
FD_ZERO(&readfds);
|
|
Packit Service |
1ec7f4 |
FD_SET(fd, &readfds);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* receive and digest all the acknowledgments from the kernel. */
|
|
Packit Service |
1ec7f4 |
ret = select(fd+1, &readfds, NULL, NULL, &tv;;
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
while (ret > 0 && FD_ISSET(fd, &readfds)) {
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh = (struct nlmsghdr *)rcv_buf;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_cb_run(rcv_buf, ret, 0, portid, NULL, NULL);
|
|
Packit Service |
1ec7f4 |
/* Continue on error, make sure we get all acknowledgments */
|
|
Packit Service |
1ec7f4 |
if (ret == -1) {
|
|
Packit Service |
1ec7f4 |
mnl_err_list_node_add(err_list, errno, nlh->nlmsg_seq);
|
|
Packit Service |
1ec7f4 |
err = -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = select(fd+1, &readfds, NULL, NULL, &tv;;
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
FD_ZERO(&readfds);
|
|
Packit Service |
1ec7f4 |
FD_SET(fd, &readfds);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
return err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
enum obj_update_type {
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_TABLE_ADD,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_TABLE_FLUSH,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_ADD,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_USER_ADD,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_USER_DEL,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_USER_FLUSH,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_UPDATE,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_RENAME,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_CHAIN_ZERO,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_RULE_APPEND,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_RULE_INSERT,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_RULE_REPLACE,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_RULE_DELETE,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_RULE_FLUSH,
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
enum obj_action {
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_COMMIT,
|
|
Packit Service |
1ec7f4 |
NFT_COMPAT_ABORT,
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct obj_update {
|
|
Packit Service |
1ec7f4 |
struct list_head head;
|
|
Packit Service |
1ec7f4 |
enum obj_update_type type;
|
|
Packit Service |
1ec7f4 |
unsigned int seq;
|
|
Packit Service |
1ec7f4 |
union {
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *table;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *chain;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *rule;
|
|
Packit Service |
1ec7f4 |
void *ptr;
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
struct {
|
|
Packit Service |
1ec7f4 |
unsigned int lineno;
|
|
Packit Service |
1ec7f4 |
} error;
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int mnl_append_error(const struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
const struct obj_update *o,
|
|
Packit Service |
1ec7f4 |
const struct mnl_err *err,
|
|
Packit Service |
1ec7f4 |
char *buf, unsigned int len)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
static const char *type_name[] = {
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_TABLE_ADD] = "TABLE_ADD",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_TABLE_FLUSH] = "TABLE_FLUSH",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_ADD] = "CHAIN_ADD",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_USER_ADD] = "CHAIN_USER_ADD",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_USER_DEL] = "CHAIN_USER_DEL",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_USER_FLUSH] = "CHAIN_USER_FLUSH",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_UPDATE] = "CHAIN_UPDATE",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_RENAME] = "CHAIN_RENAME",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_CHAIN_ZERO] = "CHAIN_ZERO",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_RULE_APPEND] = "RULE_APPEND",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_RULE_INSERT] = "RULE_INSERT",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_RULE_REPLACE] = "RULE_REPLACE",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_RULE_DELETE] = "RULE_DELETE",
|
|
Packit Service |
1ec7f4 |
[NFT_COMPAT_RULE_FLUSH] = "RULE_FLUSH",
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
char errmsg[256];
|
|
Packit Service |
1ec7f4 |
char tcr[128];
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (o->error.lineno)
|
|
Packit Service |
1ec7f4 |
snprintf(errmsg, sizeof(errmsg), "\nline %u: %s failed (%s)",
|
|
Packit Service |
1ec7f4 |
o->error.lineno, type_name[o->type], strerror(err->err));
|
|
Packit Service |
1ec7f4 |
else
|
|
Packit Service |
1ec7f4 |
snprintf(errmsg, sizeof(errmsg), " %s failed (%s)",
|
|
Packit Service |
1ec7f4 |
type_name[o->type], strerror(err->err));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
switch (o->type) {
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_FLUSH:
|
|
Packit Service |
1ec7f4 |
snprintf(tcr, sizeof(tcr), "table %s",
|
|
Packit Service |
1ec7f4 |
nftnl_table_get_str(o->table, NFTNL_TABLE_NAME));
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ZERO:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_DEL:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_FLUSH:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_UPDATE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_RENAME:
|
|
Packit Service |
1ec7f4 |
snprintf(tcr, sizeof(tcr), "chain %s",
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(o->chain, NFTNL_CHAIN_NAME));
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_APPEND:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_INSERT:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_REPLACE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_DELETE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_FLUSH:
|
|
Packit Service |
1ec7f4 |
snprintf(tcr, sizeof(tcr), "rule in chain %s",
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(o->rule, NFTNL_RULE_CHAIN));
|
|
Packit Service |
1ec7f4 |
#if 0
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nft_rule_print_save(o->rule, NFT_RULE_APPEND, FMT_NOCOUNTS);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
#endif
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return snprintf(buf, len, "%s: %s", errmsg, tcr);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct obj_update *obj;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
obj = calloc(1, sizeof(struct obj_update));
|
|
Packit Service |
1ec7f4 |
if (obj == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
obj->ptr = ptr;
|
|
Packit Service |
1ec7f4 |
obj->error.lineno = h->error.lineno;
|
|
Packit Service |
1ec7f4 |
obj->type = type;
|
|
Packit Service |
1ec7f4 |
list_add_tail(&obj->head, &h->obj_list);
|
|
Packit Service |
1ec7f4 |
h->obj_list_num++;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int batch_table_add(struct nft_handle *h, enum obj_update_type type,
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
return batch_add(h, type, t);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int batch_chain_add(struct nft_handle *h, enum obj_update_type type,
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
return batch_add(h, type, c);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
return batch_add(h, type, r);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = {
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_RAW] = {
|
|
Packit Service |
1ec7f4 |
.name = "raw",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "PREROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -300, /* NF_IP_PRI_RAW */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_PRE_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -300, /* NF_IP_PRI_RAW */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_MANGLE] = {
|
|
Packit Service |
1ec7f4 |
.name = "mangle",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "PREROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -150, /* NF_IP_PRI_MANGLE */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_PRE_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -150, /* NF_IP_PRI_MANGLE */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "FORWARD",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -150, /* NF_IP_PRI_MANGLE */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_FORWARD,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "route",
|
|
Packit Service |
1ec7f4 |
.prio = -150, /* NF_IP_PRI_MANGLE */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "POSTROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = -150, /* NF_IP_PRI_MANGLE */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_POST_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_FILTER] = {
|
|
Packit Service |
1ec7f4 |
.name = "filter",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 0, /* NF_IP_PRI_FILTER */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "FORWARD",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 0, /* NF_IP_PRI_FILTER */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_FORWARD,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 0, /* NF_IP_PRI_FILTER */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_SECURITY] = {
|
|
Packit Service |
1ec7f4 |
.name = "security",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 150, /* NF_IP_PRI_SECURITY */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "FORWARD",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 150, /* NF_IP_PRI_SECURITY */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_FORWARD,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = 150, /* NF_IP_PRI_SECURITY */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_NAT] = {
|
|
Packit Service |
1ec7f4 |
.name = "nat",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "PREROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "nat",
|
|
Packit Service |
1ec7f4 |
.prio = -100, /* NF_IP_PRI_NAT_DST */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_PRE_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "nat",
|
|
Packit Service |
1ec7f4 |
.prio = 100, /* NF_IP_PRI_NAT_SRC */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "POSTROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "nat",
|
|
Packit Service |
1ec7f4 |
.prio = 100, /* NF_IP_PRI_NAT_SRC */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_POST_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "nat",
|
|
Packit Service |
1ec7f4 |
.prio = -100, /* NF_IP_PRI_NAT_DST */
|
|
Packit Service |
1ec7f4 |
.hook = NF_INET_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter_arp.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct builtin_table xtables_arp[NFT_TABLE_MAX] = {
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_FILTER] = {
|
|
Packit Service |
1ec7f4 |
.name = "filter",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_IP_PRI_FILTER,
|
|
Packit Service |
1ec7f4 |
.hook = NF_ARP_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_IP_PRI_FILTER,
|
|
Packit Service |
1ec7f4 |
.hook = NF_ARP_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#include <linux/netfilter_bridge.h>
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct builtin_table xtables_bridge[NFT_TABLE_MAX] = {
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_FILTER] = {
|
|
Packit Service |
1ec7f4 |
.name = "filter",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "INPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_FILTER_BRIDGED,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_LOCAL_IN,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "FORWARD",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_FILTER_BRIDGED,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_FORWARD,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_FILTER_BRIDGED,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
[NFT_TABLE_NAT] = {
|
|
Packit Service |
1ec7f4 |
.name = "nat",
|
|
Packit Service |
1ec7f4 |
.chains = {
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "PREROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_NAT_DST_BRIDGED,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_PRE_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "OUTPUT",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_NAT_DST_OTHER,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_LOCAL_OUT,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
.name = "POSTROUTING",
|
|
Packit Service |
1ec7f4 |
.type = "filter",
|
|
Packit Service |
1ec7f4 |
.prio = NF_BR_PRI_NAT_SRC,
|
|
Packit Service |
1ec7f4 |
.hook = NF_BR_POST_ROUTING,
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
},
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_table_builtin_add(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
struct builtin_table *_t)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (_t->initialized)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_alloc();
|
|
Packit Service |
1ec7f4 |
if (t == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_chain *
|
|
Packit Service |
1ec7f4 |
nft_chain_builtin_alloc(struct builtin_table *table,
|
|
Packit Service |
1ec7f4 |
struct builtin_chain *chain, int policy)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_alloc();
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table->name);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain->name);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_TYPE, (char *)chain->type);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return c;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_chain_builtin_add(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
struct builtin_table *table,
|
|
Packit Service |
1ec7f4 |
struct builtin_chain *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nft_chain_builtin_alloc(table, chain, NF_ACCEPT);
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* find if built-in table already exists */
|
|
Packit Service |
1ec7f4 |
struct builtin_table *
|
|
Packit Service |
1ec7f4 |
nft_table_builtin_find(struct nft_handle *h, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int i;
|
|
Packit Service |
1ec7f4 |
bool found = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i = 0; i < NFT_TABLE_MAX; i++) {
|
|
Packit Service |
1ec7f4 |
if (h->tables[i].name == NULL)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(h->tables[i].name, table) != 0)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
found = true;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return found ? &h->tables[i] : NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* find if built-in chain already exists */
|
|
Packit Service |
1ec7f4 |
struct builtin_chain *
|
|
Packit Service |
1ec7f4 |
nft_chain_builtin_find(struct builtin_table *t, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int i;
|
|
Packit Service |
1ec7f4 |
bool found = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
|
|
Packit Service |
1ec7f4 |
if (strcmp(t->chains[i].name, chain) != 0)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
found = true;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
return found ? &t->chains[i] : NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_chain_builtin_init(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
struct builtin_table *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
int i;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Initialize built-in chains if they don't exist yet */
|
|
Packit Service |
1ec7f4 |
for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) {
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nft_chain_list_find(list, table->name,
|
|
Packit Service |
1ec7f4 |
table->chains[i].name);
|
|
Packit Service |
1ec7f4 |
if (c != NULL)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_chain_builtin_add(h, table, &table->chains[i]);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_xt_builtin_init(struct nft_handle *h, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct builtin_table *t;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nft_table_builtin_find(h, table);
|
|
Packit Service |
1ec7f4 |
if (t == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (t->initialized)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nft_table_builtin_add(h, t) < 0)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_chain_builtin_init(h, t);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t->initialized = true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static bool nft_chain_builtin(struct nftnl_chain *c)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
/* Check if this chain has hook number, in that case is built-in.
|
|
Packit Service |
1ec7f4 |
* Should we better export the flags to user-space via nf_tables?
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
return nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM) != NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_restart(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
mnl_socket_close(h->nl);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->nl = mnl_socket_open(NETLINK_NETFILTER);
|
|
Packit Service |
1ec7f4 |
if (h->nl == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->portid = mnl_socket_get_portid(h->nl);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_init(struct nft_handle *h, struct builtin_table *t)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
h->nl = mnl_socket_open(NETLINK_NETFILTER);
|
|
Packit Service |
1ec7f4 |
if (h->nl == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
|
Packit Service |
1ec7f4 |
mnl_socket_close(h->nl);
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->portid = mnl_socket_get_portid(h->nl);
|
|
Packit Service |
1ec7f4 |
h->tables = t;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
INIT_LIST_HEAD(&h->obj_list);
|
|
Packit Service |
1ec7f4 |
INIT_LIST_HEAD(&h->err_list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __flush_rule_cache(struct nftnl_rule *r, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *tablename = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!strcmp(nftnl_rule_get_str(r, NFTNL_RULE_TABLE), tablename)) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_del(r);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void flush_rule_cache(struct nft_handle *h, const char *tablename)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
if (!h->rule_cache)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (tablename) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_foreach(h->rule_cache, __flush_rule_cache,
|
|
Packit Service |
1ec7f4 |
(void *)tablename);
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_free(h->rule_cache);
|
|
Packit Service |
1ec7f4 |
h->rule_cache = NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *tablename = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!strcmp(nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), tablename)) {
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_del(c);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_free(c);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void flush_chain_cache(struct nft_handle *h, const char *tablename)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
if (!h->chain_cache)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (tablename) {
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_foreach(h->chain_cache, __flush_chain_cache,
|
|
Packit Service |
1ec7f4 |
(void *)tablename);
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_free(h->chain_cache);
|
|
Packit Service |
1ec7f4 |
h->chain_cache = NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
void nft_fini(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
flush_chain_cache(h, NULL);
|
|
Packit Service |
1ec7f4 |
flush_rule_cache(h, NULL);
|
|
Packit Service |
1ec7f4 |
mnl_socket_close(h->nl);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_chain_print_debug(struct nftnl_chain *c, struct nlmsghdr *nlh)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
#ifdef NLDEBUG
|
|
Packit Service |
1ec7f4 |
char tmp[1024];
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
|
|
Packit Service |
1ec7f4 |
printf("DEBUG: chain: %s\n", tmp);
|
|
Packit Service |
1ec7f4 |
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
|
|
Packit Service |
1ec7f4 |
#endif
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_chain *nft_chain_new(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
const char *table, const char *chain,
|
|
Packit Service |
1ec7f4 |
int policy,
|
|
Packit Service |
1ec7f4 |
const struct xt_counters *counters)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
struct builtin_table *_t;
|
|
Packit Service |
1ec7f4 |
struct builtin_chain *_c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
_t = nft_table_builtin_find(h, table);
|
|
Packit Service |
1ec7f4 |
if (!_t) {
|
|
Packit Service |
1ec7f4 |
errno = ENXIO;
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* if this built-in table does not exists, create it */
|
|
Packit Service |
1ec7f4 |
nft_table_builtin_add(h, _t);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
_c = nft_chain_builtin_find(_t, chain);
|
|
Packit Service |
1ec7f4 |
if (_c != NULL) {
|
|
Packit Service |
1ec7f4 |
/* This is a built-in chain */
|
|
Packit Service |
1ec7f4 |
c = nft_chain_builtin_alloc(_t, _c, policy);
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (counters) {
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES,
|
|
Packit Service |
1ec7f4 |
counters->bcnt);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS,
|
|
Packit Service |
1ec7f4 |
counters->pcnt);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return c;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_set(struct nft_handle *h, const char *table,
|
|
Packit Service |
1ec7f4 |
const char *chain, const char *policy,
|
|
Packit Service |
1ec7f4 |
const struct xt_counters *counters)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c = NULL;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_chain_set;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(policy, "DROP") == 0)
|
|
Packit Service |
1ec7f4 |
c = nft_chain_new(h, table, chain, NF_DROP, counters);
|
|
Packit Service |
1ec7f4 |
else if (strcmp(policy, "ACCEPT") == 0)
|
|
Packit Service |
1ec7f4 |
c = nft_chain_new(h, table, chain, NF_ACCEPT, counters);
|
|
Packit Service |
1ec7f4 |
else
|
|
Packit Service |
1ec7f4 |
errno = EINVAL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
void *info;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set(e, NFTNL_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(e, NFTNL_EXPR_MT_REV, m->u.user.revision);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
info = calloc(1, m->u.match_size);
|
|
Packit Service |
1ec7f4 |
if (info == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
memcpy(info, m->data, m->u.match_size - sizeof(*m));
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set(e, NFTNL_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct xt_rateinfo *rinfo = (void *)m->data;
|
|
Packit Service |
1ec7f4 |
static const uint32_t mult[] = {
|
|
Packit Service |
1ec7f4 |
XT_LIMIT_SCALE*24*60*60, /* day */
|
|
Packit Service |
1ec7f4 |
XT_LIMIT_SCALE*60*60, /* hour */
|
|
Packit Service |
1ec7f4 |
XT_LIMIT_SCALE*60, /* min */
|
|
Packit Service |
1ec7f4 |
XT_LIMIT_SCALE, /* sec */
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
int i;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("limit");
|
|
Packit Service |
1ec7f4 |
if (!expr)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i = 1; i < ARRAY_SIZE(mult); i++) {
|
|
Packit Service |
1ec7f4 |
if (rinfo->avg > mult[i] ||
|
|
Packit Service |
1ec7f4 |
mult[i] / rinfo->avg < mult[i] % rinfo->avg)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_TYPE, NFT_LIMIT_PKTS);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_FLAGS, 0);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_RATE,
|
|
Packit Service |
1ec7f4 |
mult[i - 1] / rinfo->avg);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_UNIT,
|
|
Packit Service |
1ec7f4 |
mult[i - 1] / XT_LIMIT_SCALE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_BURST, rinfo->burst);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_match(struct nftnl_rule *r, struct xt_entry_match *m)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!strcmp(m->u.user.name, "limit"))
|
|
Packit Service |
1ec7f4 |
return add_nft_limit(r, m);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("match");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = __add_match(expr, m);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
void *info;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set(e, NFTNL_EXPR_TG_NAME, t->u.user.name,
|
|
Packit Service |
1ec7f4 |
strlen(t->u.user.name));
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(e, NFTNL_EXPR_TG_REV, t->u.user.revision);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
info = calloc(1, t->u.target_size);
|
|
Packit Service |
1ec7f4 |
if (info == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
memcpy(info, t->data, t->u.target_size - sizeof(*t));
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set(e, NFTNL_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int add_meta_nftrace(struct nftnl_rule *r)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("immediate");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG32_01);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u8(expr, NFTNL_EXPR_IMM_DATA, 1);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("meta");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, NFT_META_NFTRACE);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_SREG, NFT_REG32_01);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_target(struct nftnl_rule *r, struct xt_entry_target *t)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(t->u.user.name, "TRACE") == 0)
|
|
Packit Service |
1ec7f4 |
return add_meta_nftrace(r);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("target");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = __add_target(expr, t);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_jumpto(struct nftnl_rule *r, const char *name, int verdict)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("immediate");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_VERDICT, verdict);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_str(expr, NFTNL_EXPR_IMM_CHAIN, (char *)name);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_verdict(struct nftnl_rule *r, int verdict)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("immediate");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_VERDICT, verdict);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_action(struct nftnl_rule *r, struct iptables_command_state *cs,
|
|
Packit Service |
1ec7f4 |
bool goto_set)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If no target at all, add nothing (default to continue) */
|
|
Packit Service |
1ec7f4 |
if (cs->target != NULL) {
|
|
Packit Service |
1ec7f4 |
/* Standard target? */
|
|
Packit Service |
1ec7f4 |
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
|
|
Packit Service |
1ec7f4 |
ret = add_verdict(r, NF_ACCEPT);
|
|
Packit Service |
1ec7f4 |
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
|
|
Packit Service |
1ec7f4 |
ret = add_verdict(r, NF_DROP);
|
|
Packit Service |
1ec7f4 |
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
|
|
Packit Service |
1ec7f4 |
ret = add_verdict(r, NFT_RETURN);
|
|
Packit Service |
1ec7f4 |
else
|
|
Packit Service |
1ec7f4 |
ret = add_target(r, cs->target->t);
|
|
Packit Service |
1ec7f4 |
} else if (strlen(cs->jumpto) > 0) {
|
|
Packit Service |
1ec7f4 |
/* Not standard, then it's a go / jump to chain */
|
|
Packit Service |
1ec7f4 |
if (goto_set)
|
|
Packit Service |
1ec7f4 |
ret = add_jumpto(r, cs->jumpto, NFT_GOTO);
|
|
Packit Service |
1ec7f4 |
else
|
|
Packit Service |
1ec7f4 |
ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_rule_print_debug(struct nftnl_rule *r, struct nlmsghdr *nlh)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
#ifdef NLDEBUG
|
|
Packit Service |
1ec7f4 |
char tmp[1024];
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
|
|
Packit Service |
1ec7f4 |
printf("DEBUG: rule: %s\n", tmp);
|
|
Packit Service |
1ec7f4 |
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
|
|
Packit Service |
1ec7f4 |
#endif
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_alloc("counter");
|
|
Packit Service |
1ec7f4 |
if (expr == NULL)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(expr, NFTNL_EXPR_CTR_PACKETS, packets);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(expr, NFTNL_EXPR_CTR_BYTES, bytes);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
enum udata_type {
|
|
Packit Service |
1ec7f4 |
UDATA_TYPE_COMMENT,
|
|
Packit Service |
1ec7f4 |
__UDATA_TYPE_MAX,
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
#define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1)
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int add_comment(struct nftnl_rule *r, const char *comment)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_udata_buf *udata;
|
|
Packit Service |
1ec7f4 |
uint32_t len;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len))
|
|
Packit Service |
1ec7f4 |
return -EALREADY;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
|
|
Packit Service |
1ec7f4 |
if (!udata)
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strnlen(comment, 255) == 255)
|
|
Packit Service |
1ec7f4 |
return -ENOSPC;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment))
|
|
Packit Service |
1ec7f4 |
return -ENOMEM;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
|
|
Packit Service |
1ec7f4 |
nftnl_udata_buf_data(udata),
|
|
Packit Service |
1ec7f4 |
nftnl_udata_buf_len(udata));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_udata_buf_free(udata);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int parse_udata_cb(const struct nftnl_udata *attr, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
unsigned char *value = nftnl_udata_get(attr);
|
|
Packit Service |
1ec7f4 |
uint8_t type = nftnl_udata_type(attr);
|
|
Packit Service |
1ec7f4 |
uint8_t len = nftnl_udata_len(attr);
|
|
Packit Service |
1ec7f4 |
const struct nftnl_udata **tb = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
switch (type) {
|
|
Packit Service |
1ec7f4 |
case UDATA_TYPE_COMMENT:
|
|
Packit Service |
1ec7f4 |
if (value[len - 1] != '\0')
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
default:
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
tb[type] = attr;
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
char *get_comment(const void *data, uint32_t data_len)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_udata_parse(data, data_len, parse_udata_cb, tb) < 0)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!tb[UDATA_TYPE_COMMENT])
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return nftnl_udata_get(tb[UDATA_TYPE_COMMENT]);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
void add_compat(struct nftnl_rule *r, uint32_t proto, bool inv)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_PROTO, proto);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_FLAGS,
|
|
Packit Service |
1ec7f4 |
inv ? NFT_RULE_COMPAT_F_INV : 0);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_rule *
|
|
Packit Service |
1ec7f4 |
nft_rule_new(struct nft_handle *h, const char *chain, const char *table,
|
|
Packit Service |
1ec7f4 |
void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_alloc();
|
|
Packit Service |
1ec7f4 |
if (r == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, h->family);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (h->ops->add(r, data) < 0)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return r;
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int
|
|
Packit Service |
1ec7f4 |
nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
|
|
Packit Service |
1ec7f4 |
void *data, uint64_t handle, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
int type;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_append;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_new(h, chain, table, data);
|
|
Packit Service |
1ec7f4 |
if (r == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (handle > 0) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set(r, NFTNL_RULE_HANDLE, &handle);
|
|
Packit Service |
1ec7f4 |
type = NFT_COMPAT_RULE_REPLACE;
|
|
Packit Service |
1ec7f4 |
} else
|
|
Packit Service |
1ec7f4 |
type = NFT_COMPAT_RULE_APPEND;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (batch_rule_add(h, type, r) < 0) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nft_rule_list_get(h))
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_add_tail(r, h->rule_cache);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
void
|
|
Packit Service |
1ec7f4 |
nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
|
|
Packit Service |
1ec7f4 |
unsigned int format)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
|
|
Packit Service |
1ec7f4 |
int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
|
|
Packit Service |
1ec7f4 |
struct iptables_command_state cs = {};
|
|
Packit Service |
1ec7f4 |
struct nft_family_ops *ops;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ops = nft_family_ops_lookup(family);
|
|
Packit Service |
1ec7f4 |
ops->rule_to_cs(r, &cs);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters)
|
|
Packit Service |
1ec7f4 |
ops->save_counters(&cs);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* print chain name */
|
|
Packit Service |
1ec7f4 |
switch(type) {
|
|
Packit Service |
1ec7f4 |
case NFT_RULE_APPEND:
|
|
Packit Service |
1ec7f4 |
printf("-A %s ", chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_RULE_DEL:
|
|
Packit Service |
1ec7f4 |
printf("-D %s ", chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (ops->save_rule)
|
|
Packit Service |
1ec7f4 |
ops->save_rule(&cs, format);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (ops->clear_cs)
|
|
Packit Service |
1ec7f4 |
ops->clear_cs(&cs);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_alloc();
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
|
|
Packit Service |
1ec7f4 |
goto out;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_add_tail(c, list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
out:
|
|
Packit Service |
1ec7f4 |
nftnl_chain_free(c);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
char buf[16536];
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (h->chain_cache)
|
|
Packit Service |
1ec7f4 |
return h->chain_cache;
|
|
Packit Service |
1ec7f4 |
retry:
|
|
Packit Service |
1ec7f4 |
list = nftnl_chain_list_alloc();
|
|
Packit Service |
1ec7f4 |
if (list == NULL) {
|
|
Packit Service |
1ec7f4 |
errno = ENOMEM;
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
|
|
Packit Service |
1ec7f4 |
NLM_F_DUMP, h->seq);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list);
|
|
Packit Service |
1ec7f4 |
if (ret < 0 && errno == EINTR) {
|
|
Packit Service |
1ec7f4 |
assert(nft_restart(h) >= 0);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_free(list);
|
|
Packit Service |
1ec7f4 |
goto retry;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->chain_cache = list;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return list;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static const char *policy_name[NF_ACCEPT+1] = {
|
|
Packit Service |
1ec7f4 |
[NF_DROP] = "DROP",
|
|
Packit Service |
1ec7f4 |
[NF_ACCEPT] = "ACCEPT",
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
|
|
Packit Service |
1ec7f4 |
const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nft_family_ops *ops;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ops = nft_family_ops_lookup(h->family);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_table =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *policy = NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, chain_table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nft_chain_builtin(c)) {
|
|
Packit Service |
1ec7f4 |
uint32_t pol = NF_ACCEPT;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
|
|
Packit Service |
1ec7f4 |
pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
|
|
Packit Service |
1ec7f4 |
policy = policy_name[pol];
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (ops->save_chain)
|
|
Packit Service |
1ec7f4 |
ops->save_chain(c, policy);
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_alloc();
|
|
Packit Service |
1ec7f4 |
if (r == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
|
|
Packit Service |
1ec7f4 |
goto out;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_add_tail(r, list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
out:
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_free(list);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
char buf[16536];
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (h->rule_cache)
|
|
Packit Service |
1ec7f4 |
return h->rule_cache;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
retry:
|
|
Packit Service |
1ec7f4 |
list = nftnl_rule_list_alloc();
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
|
|
Packit Service |
1ec7f4 |
NLM_F_DUMP, h->seq);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list);
|
|
Packit Service |
1ec7f4 |
if (ret < 0) {
|
|
Packit Service |
1ec7f4 |
if (errno == EINTR) {
|
|
Packit Service |
1ec7f4 |
assert(nft_restart(h) >= 0);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_free(list);
|
|
Packit Service |
1ec7f4 |
goto retry;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_free(list);
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->rule_cache = list;
|
|
Packit Service |
1ec7f4 |
return list;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (r != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *rule_table =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, rule_table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_rule_print_save(r, NFT_RULE_APPEND, format);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void
|
|
Packit Service |
1ec7f4 |
__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_alloc();
|
|
Packit Service |
1ec7f4 |
if (r == NULL)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r) < 0)
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct chain_user_flush_data {
|
|
Packit Service |
1ec7f4 |
struct nft_handle *handle;
|
|
Packit Service |
1ec7f4 |
const char *table;
|
|
Packit Service |
1ec7f4 |
const char *chain;
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
struct chain_user_flush_data *d = data;
|
|
Packit Service |
1ec7f4 |
struct nft_handle *h = d->handle;
|
|
Packit Service |
1ec7f4 |
const char *table = d->table;
|
|
Packit Service |
1ec7f4 |
const char *chain = d->chain;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, table_name) != 0)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
|
|
Packit Service |
1ec7f4 |
__nft_rule_flush(h, table, chain);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
|
|
Packit Service |
1ec7f4 |
const char *table, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct chain_user_flush_data d = {
|
|
Packit Service |
1ec7f4 |
.handle = h,
|
|
Packit Service |
1ec7f4 |
.table = table,
|
|
Packit Service |
1ec7f4 |
.chain = chain,
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_chain_user_flush;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_foreach(list, __nft_chain_user_flush, &d);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
|
|
Packit Service |
1ec7f4 |
bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_flush;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL) {
|
|
Packit Service |
1ec7f4 |
ret = 1;
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL) {
|
|
Packit Service |
1ec7f4 |
ret = 1;
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *table_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, table_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL && strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
fprintf(stdout, "Flushing chain `%s'\n", chain_name);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
__nft_rule_flush(h, table_name, chain_name);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
flush_rule_cache(h, table);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_chain_user_add;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_alloc();
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_add(c, h->chain_cache);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* From linux/netlink.h */
|
|
Packit Service |
1ec7f4 |
#ifndef NLM_F_NONREC
|
|
Packit Service |
1ec7f4 |
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
|
Packit Service |
1ec7f4 |
#endif
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_user_del(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
int deleted_ctr = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_chain_user_del;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *table_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* don't delete built-in chain */
|
|
Packit Service |
1ec7f4 |
if (nft_chain_builtin(c))
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, table_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL && strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
fprintf(stdout, "Deleting chain `%s'\n", chain);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (ret < 0)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
deleted_ctr++;
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_del(c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* chain not found */
|
|
Packit Service |
1ec7f4 |
if (chain != NULL && deleted_ctr == 0) {
|
|
Packit Service |
1ec7f4 |
ret = -1;
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *
|
|
Packit Service |
1ec7f4 |
nft_chain_list_find(struct nftnl_chain_list *list,
|
|
Packit Service |
1ec7f4 |
const char *table, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *table_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, table_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return c;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_chain *
|
|
Packit Service |
1ec7f4 |
nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return nft_chain_list_find(list, table, chain);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
bool nft_chain_exists(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
const char *table, const char *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct builtin_table *t = nft_table_builtin_find(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* xtables does not support custom tables */
|
|
Packit Service |
1ec7f4 |
if (!t)
|
|
Packit Service |
1ec7f4 |
return false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nft_chain_builtin_find(t, chain))
|
|
Packit Service |
1ec7f4 |
return true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return !!nft_chain_find(h, table, chain);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_user_rename(struct nft_handle *h,const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, const char *newname)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
uint64_t handle;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_chain_user_add;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Config load changed errno. Ensure genuine info for our callers. */
|
|
Packit Service |
1ec7f4 |
errno = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Find the old chain to be renamed */
|
|
Packit Service |
1ec7f4 |
c = nft_chain_find(h, table, chain);
|
|
Packit Service |
1ec7f4 |
if (c == NULL) {
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
handle = nftnl_chain_get_u64(c, NFTNL_CHAIN_HANDLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Now prepare the new name for the chain */
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_alloc();
|
|
Packit Service |
1ec7f4 |
if (c == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *list = data;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_alloc();
|
|
Packit Service |
1ec7f4 |
if (t == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_table_nlmsg_parse(nlh, t) < 0)
|
|
Packit Service |
1ec7f4 |
goto out;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_add_tail(t, list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
out:
|
|
Packit Service |
1ec7f4 |
nftnl_table_free(t);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return MNL_CB_OK;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
char buf[16536];
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *list;
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
retry:
|
|
Packit Service |
1ec7f4 |
list = nftnl_table_list_alloc();
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
|
|
Packit Service |
1ec7f4 |
NLM_F_DUMP, h->seq);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
|
|
Packit Service |
1ec7f4 |
if (ret < 0 && errno == EINTR) {
|
|
Packit Service |
1ec7f4 |
assert(nft_restart(h) >= 0);
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(list);
|
|
Packit Service |
1ec7f4 |
goto retry;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return list;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
bool nft_table_find(struct nft_handle *h, const char *tablename)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
bool ret = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nftnl_table_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_table_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (t != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *this_tablename =
|
|
Packit Service |
1ec7f4 |
nftnl_table_get(t, NFTNL_TABLE_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(tablename, this_tablename) == 0) {
|
|
Packit Service |
1ec7f4 |
ret = true;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_for_each_table(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
int (*func)(struct nft_handle *h, const char *tablename, bool counters),
|
|
Packit Service |
1ec7f4 |
bool counters)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nftnl_table_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_table_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (t != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *tablename =
|
|
Packit Service |
1ec7f4 |
nftnl_table_get(t, NFTNL_TABLE_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
func(h, tablename, counters);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(list);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __nft_table_flush(struct nft_handle *h, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct builtin_table *_t;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_alloc();
|
|
Packit Service |
1ec7f4 |
if (t == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_table_set_str(t, NFTNL_TABLE_NAME, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
batch_table_add(h, NFT_COMPAT_TABLE_FLUSH, t);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
_t = nft_table_builtin_find(h, table);
|
|
Packit Service |
1ec7f4 |
assert(_t);
|
|
Packit Service |
1ec7f4 |
_t->initialized = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
flush_chain_cache(h, table);
|
|
Packit Service |
1ec7f4 |
flush_rule_cache(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_table_flush(struct nft_handle *h, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *t;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_table_flush;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nftnl_table_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL) {
|
|
Packit Service |
1ec7f4 |
ret = -1;
|
|
Packit Service |
1ec7f4 |
goto err_out;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_table_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL) {
|
|
Packit Service |
1ec7f4 |
ret = -1;
|
|
Packit Service |
1ec7f4 |
goto err_table_list;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (t != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *table_name =
|
|
Packit Service |
1ec7f4 |
nftnl_table_get_str(t, NFTNL_TABLE_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table_name, table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = __nft_table_flush(h, table);
|
|
Packit Service |
1ec7f4 |
if (ret < 0)
|
|
Packit Service |
1ec7f4 |
goto err_table_iter;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
t = nftnl_table_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!h->rule_cache) {
|
|
Packit Service |
1ec7f4 |
h->rule_cache = nftnl_rule_list_alloc();
|
|
Packit Service |
1ec7f4 |
if (h->rule_cache == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err_table_iter:
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
err_table_list:
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(list);
|
|
Packit Service |
1ec7f4 |
err_out:
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
void nft_table_new(struct nft_handle *h, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list,
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_del(r);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r);
|
|
Packit Service |
1ec7f4 |
if (ret < 0) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_rule *
|
|
Packit Service |
1ec7f4 |
nft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list,
|
|
Packit Service |
1ec7f4 |
const char *chain, const char *table, void *data, int rulenum)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
int rule_ctr = 0;
|
|
Packit Service |
1ec7f4 |
bool found = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (r != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *rule_table =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *rule_chain =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, rule_table) != 0 ||
|
|
Packit Service |
1ec7f4 |
strcmp(chain, rule_chain) != 0) {
|
|
Packit Service |
1ec7f4 |
DEBUGP("different chain / table\n");
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (rulenum >= 0) {
|
|
Packit Service |
1ec7f4 |
/* Delete by rule number case */
|
|
Packit Service |
1ec7f4 |
if (rule_ctr == rulenum) {
|
|
Packit Service |
1ec7f4 |
found = true;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
found = h->ops->rule_find(h->ops, r, data);
|
|
Packit Service |
1ec7f4 |
if (found)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
rule_ctr++;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return found ? r : NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_check(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, void *data, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_check;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, data, -1);
|
|
Packit Service |
1ec7f4 |
if (r == NULL) {
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_delete(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, void *data, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_delete;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, data, -1);
|
|
Packit Service |
1ec7f4 |
if (r != NULL) {
|
|
Packit Service |
1ec7f4 |
ret =__nft_rule_del(h, list, r);
|
|
Packit Service |
1ec7f4 |
if (ret < 0)
|
|
Packit Service |
1ec7f4 |
errno = ENOMEM;
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
|
|
Packit Service |
1ec7f4 |
} else
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static struct nftnl_rule *
|
|
Packit Service |
1ec7f4 |
nft_rule_add(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, struct iptables_command_state *cs,
|
|
Packit Service |
1ec7f4 |
uint64_t handle, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_new(h, chain, table, cs);
|
|
Packit Service |
1ec7f4 |
if (r == NULL)
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (handle > 0)
|
|
Packit Service |
1ec7f4 |
nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(r);
|
|
Packit Service |
1ec7f4 |
return NULL;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
h->ops->print_rule(r, 0, FMT_PRINT_RULE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return r;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_insert(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, void *data, int rulenum, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r, *new_rule;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
uint64_t handle = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_insert;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (rulenum > 0) {
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, data, rulenum);
|
|
Packit Service |
1ec7f4 |
if (r == NULL) {
|
|
Packit Service |
1ec7f4 |
/* special case: iptables allows to insert into
|
|
Packit Service |
1ec7f4 |
* rule_count + 1 position.
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, data,
|
|
Packit Service |
1ec7f4 |
rulenum - 1);
|
|
Packit Service |
1ec7f4 |
if (r != NULL)
|
|
Packit Service |
1ec7f4 |
return nft_rule_append(h, chain, table, data,
|
|
Packit Service |
1ec7f4 |
0, verbose);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
|
|
Packit Service |
1ec7f4 |
DEBUGP("adding after rule handle %"PRIu64"\n", handle);
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
new_rule = nft_rule_add(h, chain, table, data, handle, verbose);
|
|
Packit Service |
1ec7f4 |
if (!new_rule)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (handle)
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_insert_at(new_rule, r);
|
|
Packit Service |
1ec7f4 |
else
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_add(new_rule, h->rule_cache);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_delete_num(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, int rulenum, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_delete_num;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, NULL, rulenum);
|
|
Packit Service |
1ec7f4 |
if (r != NULL) {
|
|
Packit Service |
1ec7f4 |
DEBUGP("deleting rule by number %d\n", rulenum);
|
|
Packit Service |
1ec7f4 |
ret = __nft_rule_del(h, list, r);
|
|
Packit Service |
1ec7f4 |
if (ret < 0)
|
|
Packit Service |
1ec7f4 |
errno = ENOMEM;
|
|
Packit Service |
1ec7f4 |
} else
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_replace(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, void *data, int rulenum, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_replace;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, data, rulenum);
|
|
Packit Service |
1ec7f4 |
if (r != NULL) {
|
|
Packit Service |
1ec7f4 |
DEBUGP("replacing rule with handle=%llu\n",
|
|
Packit Service |
1ec7f4 |
(unsigned long long)
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_del(r);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = nft_rule_append(h, chain, table, data,
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
|
|
Packit Service |
1ec7f4 |
verbose);
|
|
Packit Service |
1ec7f4 |
} else
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int
|
|
Packit Service |
1ec7f4 |
__nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
|
|
Packit Service |
1ec7f4 |
int rulenum, unsigned int format,
|
|
Packit Service |
1ec7f4 |
void (*cb)(struct nftnl_rule *r, unsigned int num,
|
|
Packit Service |
1ec7f4 |
unsigned int format))
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
int rule_ctr = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (r != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *rule_table =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *rule_chain =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, rule_table) != 0 ||
|
|
Packit Service |
1ec7f4 |
strcmp(chain, rule_chain) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
rule_ctr++;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (rulenum > 0 && rule_ctr != rulenum) {
|
|
Packit Service |
1ec7f4 |
/* List by rule number case */
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
cb(r, rule_ctr, format);
|
|
Packit Service |
1ec7f4 |
if (rulenum > 0)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_rule_count(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
const char *chain, const char *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
int rule_ctr = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (r != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *rule_table =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *rule_chain =
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, rule_table) != 0 ||
|
|
Packit Service |
1ec7f4 |
strcmp(chain, rule_chain) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
rule_ctr++;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return rule_ctr;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
|
|
Packit Service |
1ec7f4 |
int rulenum, unsigned int format)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const struct nft_family_ops *ops;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
bool found = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
/* Force table and chain creation, otherwise first iptables -L
|
|
Packit Service |
1ec7f4 |
* lists no table/chains.
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
if (!list_empty(&h->obj_list)) {
|
|
Packit Service |
1ec7f4 |
nft_commit(h);
|
|
Packit Service |
1ec7f4 |
flush_chain_cache(h, NULL);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ops = nft_family_ops_lookup(h->family);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nft_is_table_compatible(h, table)) {
|
|
Packit Service |
1ec7f4 |
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain && rulenum) {
|
|
Packit Service |
1ec7f4 |
__nft_rule_list(h, chain, table,
|
|
Packit Service |
1ec7f4 |
rulenum, format, ops->print_rule);
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!chain && ops->print_table_header)
|
|
Packit Service |
1ec7f4 |
ops->print_table_header(table);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_table =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
uint32_t policy =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
|
|
Packit Service |
1ec7f4 |
uint32_t refs =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
|
|
Packit Service |
1ec7f4 |
struct xt_counters ctrs = {
|
|
Packit Service |
1ec7f4 |
.pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
|
|
Packit Service |
1ec7f4 |
.bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
bool basechain = false;
|
|
Packit Service |
1ec7f4 |
uint32_t entries;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
|
|
Packit Service |
1ec7f4 |
basechain = true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, chain_table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
if (chain) {
|
|
Packit Service |
1ec7f4 |
if (strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
else if (ops->print_table_header)
|
|
Packit Service |
1ec7f4 |
ops->print_table_header(table);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (found)
|
|
Packit Service |
1ec7f4 |
printf("\n");
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
entries = nft_rule_count(h, chain_name, table);
|
|
Packit Service |
1ec7f4 |
ops->print_header(format, chain_name, policy_name[policy],
|
|
Packit Service |
1ec7f4 |
&ctrs, basechain, refs - entries, entries);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
__nft_rule_list(h, chain_name, table,
|
|
Packit Service |
1ec7f4 |
rulenum, format, ops->print_rule);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
found = true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* we printed the chain we wanted, stop processing. */
|
|
Packit Service |
1ec7f4 |
if (chain)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
if (chain && !found)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void
|
|
Packit Service |
1ec7f4 |
list_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
nft_rule_print_save(r, NFT_RULE_APPEND, format);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, struct nftnl_chain_list *list,
|
|
Packit Service |
1ec7f4 |
int counters)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_table =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
uint32_t policy =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, chain_table) != 0 ||
|
|
Packit Service |
1ec7f4 |
(chain && strcmp(chain, chain_name) != 0))
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* this is a base chain */
|
|
Packit Service |
1ec7f4 |
if (nft_chain_builtin(c)) {
|
|
Packit Service |
1ec7f4 |
printf("-P %s %s", chain_name, policy_name[policy]);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (counters) {
|
|
Packit Service |
1ec7f4 |
printf(" -c %"PRIu64" %"PRIu64"\n",
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
|
|
Packit Service |
1ec7f4 |
} else
|
|
Packit Service |
1ec7f4 |
printf("\n");
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
printf("-N %s\n", chain_name);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_list_save(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, int rulenum, int counters)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
unsigned int format = 0;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* If built-in chains don't exist for this table, create them */
|
|
Packit Service |
1ec7f4 |
if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
|
|
Packit Service |
1ec7f4 |
nft_xt_builtin_init(h, table);
|
|
Packit Service |
1ec7f4 |
/* Force table and chain creation, otherwise first iptables -L
|
|
Packit Service |
1ec7f4 |
* lists no table/chains.
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
if (!list_empty(&h->obj_list)) {
|
|
Packit Service |
1ec7f4 |
nft_commit(h);
|
|
Packit Service |
1ec7f4 |
flush_chain_cache(h, NULL);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nft_is_table_compatible(h, table)) {
|
|
Packit Service |
1ec7f4 |
xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table);
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Dump policies and custom chains first */
|
|
Packit Service |
1ec7f4 |
if (!rulenum)
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_chain_save(h, chain, table, list, counters);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Now dump out rules in this table */
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (counters < 0)
|
|
Packit Service |
1ec7f4 |
format = FMT_C_COUNTS;
|
|
Packit Service |
1ec7f4 |
else if (counters == 0)
|
|
Packit Service |
1ec7f4 |
format = FMT_NOCOUNTS;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_table =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, chain_table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
if (chain && strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = __nft_rule_list(h, chain_name, table, rulenum,
|
|
Packit Service |
1ec7f4 |
format, list_save);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* we printed the chain we wanted, stop processing. */
|
|
Packit Service |
1ec7f4 |
if (chain)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, int rulenum)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct iptables_command_state cs = {};
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_fn = nft_rule_delete;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nft_rule_find(h, list, chain, table, NULL, rulenum);
|
|
Packit Service |
1ec7f4 |
if (r == NULL) {
|
|
Packit Service |
1ec7f4 |
errno = ENOENT;
|
|
Packit Service |
1ec7f4 |
ret = 1;
|
|
Packit Service |
1ec7f4 |
goto error;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_rule_to_iptables_command_state(r, &cs);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
cs.counters.pcnt = cs.counters.bcnt = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = nft_rule_append(h, chain, table, &cs,
|
|
Packit Service |
1ec7f4 |
nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
|
|
Packit Service |
1ec7f4 |
false);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
error:
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
|
|
Packit Service |
1ec7f4 |
uint16_t flags, uint32_t seq,
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *table)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_table_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
|
|
Packit Service |
1ec7f4 |
type, h->family, flags, seq);
|
|
Packit Service |
1ec7f4 |
nftnl_table_nlmsg_build_payload(nlh, table);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
|
|
Packit Service |
1ec7f4 |
uint16_t flags, uint32_t seq,
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_chain_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
|
|
Packit Service |
1ec7f4 |
type, h->family, flags, seq);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_nlmsg_build_payload(nlh, chain);
|
|
Packit Service |
1ec7f4 |
nft_chain_print_debug(chain, nlh);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
|
|
Packit Service |
1ec7f4 |
uint16_t flags, uint32_t seq,
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *rule)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = nftnl_rule_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
|
|
Packit Service |
1ec7f4 |
type, h->family, flags, seq);
|
|
Packit Service |
1ec7f4 |
nftnl_rule_nlmsg_build_payload(nlh, rule);
|
|
Packit Service |
1ec7f4 |
nft_rule_print_debug(rule, nlh);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
switch (o->type) {
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_FLUSH:
|
|
Packit Service |
1ec7f4 |
nftnl_table_free(o->table);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ZERO:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_ADD:
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_DEL:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_FLUSH:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_UPDATE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_RENAME:
|
|
Packit Service |
1ec7f4 |
nftnl_chain_free(o->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_APPEND:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_INSERT:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_REPLACE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_DELETE:
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_FLUSH:
|
|
Packit Service |
1ec7f4 |
nftnl_rule_free(o->rule);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
h->obj_list_num--;
|
|
Packit Service |
1ec7f4 |
list_del(&o->head);
|
|
Packit Service |
1ec7f4 |
free(o);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_action(struct nft_handle *h, int action)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct obj_update *n, *tmp;
|
|
Packit Service |
1ec7f4 |
struct mnl_err *err, *ne;
|
|
Packit Service |
1ec7f4 |
unsigned int buflen, i, len;
|
|
Packit Service |
1ec7f4 |
bool show_errors = true;
|
|
Packit Service |
1ec7f4 |
char errmsg[1024];
|
|
Packit Service |
1ec7f4 |
uint32_t seq = 1;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->batch = mnl_batch_init();
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
mnl_batch_begin(h->batch, seq++);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list_for_each_entry(n, &h->obj_list, head) {
|
|
Packit Service |
1ec7f4 |
n->seq = seq++;
|
|
Packit Service |
1ec7f4 |
switch (n->type) {
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_ADD:
|
|
Packit Service |
1ec7f4 |
nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE,
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE, n->seq,
|
|
Packit Service |
1ec7f4 |
n->table);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_TABLE_FLUSH:
|
|
Packit Service |
1ec7f4 |
nft_compat_table_batch_add(h, NFT_MSG_DELTABLE,
|
|
Packit Service |
1ec7f4 |
0,
|
|
Packit Service |
1ec7f4 |
n->seq, n->table);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ADD:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_ZERO:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE, n->seq,
|
|
Packit Service |
1ec7f4 |
n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_ADD:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
|
|
Packit Service |
1ec7f4 |
NLM_F_EXCL, n->seq,
|
|
Packit Service |
1ec7f4 |
n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_DEL:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
|
|
Packit Service |
1ec7f4 |
NLM_F_NONREC, n->seq,
|
|
Packit Service |
1ec7f4 |
n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_USER_FLUSH:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
|
|
Packit Service |
1ec7f4 |
0, n->seq,
|
|
Packit Service |
1ec7f4 |
n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_UPDATE:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
|
|
Packit Service |
1ec7f4 |
h->restore ?
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE : 0,
|
|
Packit Service |
1ec7f4 |
n->seq, n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_CHAIN_RENAME:
|
|
Packit Service |
1ec7f4 |
nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, 0,
|
|
Packit Service |
1ec7f4 |
n->seq, n->chain);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_APPEND:
|
|
Packit Service |
1ec7f4 |
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE | NLM_F_APPEND,
|
|
Packit Service |
1ec7f4 |
n->seq, n->rule);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_INSERT:
|
|
Packit Service |
1ec7f4 |
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE, n->seq,
|
|
Packit Service |
1ec7f4 |
n->rule);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_REPLACE:
|
|
Packit Service |
1ec7f4 |
nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
|
|
Packit Service |
1ec7f4 |
NLM_F_CREATE | NLM_F_REPLACE,
|
|
Packit Service |
1ec7f4 |
n->seq, n->rule);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_DELETE:
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_RULE_FLUSH:
|
|
Packit Service |
1ec7f4 |
nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
|
|
Packit Service |
1ec7f4 |
n->seq, n->rule);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
mnl_nft_batch_continue(h->batch);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
switch (action) {
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_COMMIT:
|
|
Packit Service |
1ec7f4 |
mnl_batch_end(h->batch, seq++);
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case NFT_COMPAT_ABORT:
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_batch_talk(h->nl, h->batch, &h->err_list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
i = 0;
|
|
Packit Service |
1ec7f4 |
buflen = sizeof(errmsg);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
|
|
Packit Service |
1ec7f4 |
list_for_each_entry_safe(err, ne, &h->err_list, head) {
|
|
Packit Service |
1ec7f4 |
if (err->seqnum > n->seq)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (err->seqnum == n->seq && show_errors) {
|
|
Packit Service |
1ec7f4 |
if (n->error.lineno == 0)
|
|
Packit Service |
1ec7f4 |
show_errors = false;
|
|
Packit Service |
1ec7f4 |
len = mnl_append_error(h, n, err, errmsg + i, buflen);
|
|
Packit Service |
1ec7f4 |
if (len > 0 && len <= buflen) {
|
|
Packit Service |
1ec7f4 |
buflen -= len;
|
|
Packit Service |
1ec7f4 |
i += len;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
mnl_err_list_free(err);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
batch_obj_del(h, n);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
mnl_batch_reset(h->batch);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (i)
|
|
Packit Service |
1ec7f4 |
xtables_error(RESOURCE_PROBLEM, "%s", errmsg);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_commit(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
return nft_action(h, NFT_COMPAT_COMMIT);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_abort(struct nft_handle *h)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
return nft_action(h, NFT_COMPAT_ABORT);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_compatible_revision(const char *name, uint8_t rev, int opt)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct mnl_socket *nl;
|
|
Packit Service |
1ec7f4 |
char buf[16536];
|
|
Packit Service |
1ec7f4 |
struct nlmsghdr *nlh;
|
|
Packit Service |
1ec7f4 |
uint32_t portid, seq, type = 0;
|
|
Packit Service |
1ec7f4 |
uint32_t pf = AF_INET;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
switch (opt) {
|
|
Packit Service |
1ec7f4 |
case IPT_SO_GET_REVISION_MATCH:
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case IP6T_SO_GET_REVISION_MATCH:
|
|
Packit Service |
1ec7f4 |
pf = AF_INET6;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case IPT_SO_GET_REVISION_TARGET:
|
|
Packit Service |
1ec7f4 |
type = 1;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
case IP6T_SO_GET_REVISION_TARGET:
|
|
Packit Service |
1ec7f4 |
type = 1;
|
|
Packit Service |
1ec7f4 |
pf = AF_INET6;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
default:
|
|
Packit Service |
1ec7f4 |
/* No revision support (arp, ebtables), assume latest version ok */
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nlh = mnl_nlmsg_put_header(buf);
|
|
Packit Service |
1ec7f4 |
nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
|
|
Packit Service |
1ec7f4 |
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
|
Packit Service |
1ec7f4 |
nlh->nlmsg_seq = seq = time(NULL);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
|
Packit Service |
1ec7f4 |
nfg->nfgen_family = pf;
|
|
Packit Service |
1ec7f4 |
nfg->version = NFNETLINK_V0;
|
|
Packit Service |
1ec7f4 |
nfg->res_id = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
|
|
Packit Service |
1ec7f4 |
mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
|
|
Packit Service |
1ec7f4 |
mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
|
|
Packit Service |
1ec7f4 |
name, rev, type);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nl = mnl_socket_open(NETLINK_NETFILTER);
|
|
Packit Service |
1ec7f4 |
if (nl == NULL)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
portid = mnl_socket_get_portid(nl);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
|
Packit Service |
1ec7f4 |
if (ret == -1)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
mnl_socket_close(nl);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret < 0 ? 0 : 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Translates errno numbers into more human-readable form than strerror. */
|
|
Packit Service |
1ec7f4 |
const char *nft_strerror(int err)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
unsigned int i;
|
|
Packit Service |
1ec7f4 |
static struct table_struct {
|
|
Packit Service |
1ec7f4 |
void *fn;
|
|
Packit Service |
1ec7f4 |
int err;
|
|
Packit Service |
1ec7f4 |
const char *message;
|
|
Packit Service |
1ec7f4 |
} table[] =
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
{ nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_user_del, EBUSY, "Directory not empty" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_user_del, EMLINK,
|
|
Packit Service |
1ec7f4 |
"Can't delete chain with references left" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_user_add, EEXIST, "Chain already exists" },
|
|
Packit Service |
1ec7f4 |
{ nft_rule_insert, ENOENT, "Index of insertion too big" },
|
|
Packit Service |
1ec7f4 |
{ nft_rule_check, ENOENT, "Bad rule (does a matching rule exist in that chain?)" },
|
|
Packit Service |
1ec7f4 |
{ nft_rule_replace, ENOENT, "Index of replacement too big" },
|
|
Packit Service |
1ec7f4 |
{ nft_rule_delete_num, ENOENT, "Index of deletion too big" },
|
|
Packit Service |
1ec7f4 |
/* { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
|
|
Packit Service |
1ec7f4 |
{ TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
|
|
Packit Service |
1ec7f4 |
/* ENOENT for DELETE probably means no matching rule */
|
|
Packit Service |
1ec7f4 |
{ nft_rule_delete, ENOENT,
|
|
Packit Service |
1ec7f4 |
"Bad rule (does a matching rule exist in that chain?)" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_set, ENOENT, "Bad built-in chain name" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_set, EINVAL, "Bad policy name" },
|
|
Packit Service |
1ec7f4 |
{ nft_chain_set, ENXIO, "Bad table name" },
|
|
Packit Service |
1ec7f4 |
{ NULL, ELOOP, "Loop found in table" },
|
|
Packit Service |
1ec7f4 |
{ NULL, EPERM, "Permission denied (you must be root)" },
|
|
Packit Service |
1ec7f4 |
{ NULL, 0, "Incompatible with this kernel" },
|
|
Packit Service |
1ec7f4 |
{ NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
|
|
Packit Service |
1ec7f4 |
{ NULL, ENOSYS, "Will be implemented real soon. I promise ;)" },
|
|
Packit Service |
1ec7f4 |
{ NULL, ENOMEM, "Memory allocation problem" },
|
|
Packit Service |
1ec7f4 |
{ NULL, ENOENT, "No chain/target/match by that name" },
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
|
|
Packit Service |
1ec7f4 |
if ((!table[i].fn || table[i].fn == nft_fn)
|
|
Packit Service |
1ec7f4 |
&& table[i].err == err)
|
|
Packit Service |
1ec7f4 |
return table[i].message;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return strerror(err);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void xtables_config_perror(uint32_t flags, const char *fmt, ...)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
va_list args;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
va_start(args, fmt);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (flags & NFT_LOAD_VERBOSE)
|
|
Packit Service |
1ec7f4 |
vfprintf(stderr, fmt, args);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
va_end(args);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int __nft_xtables_config_load(struct nft_handle *h, const char *filename,
|
|
Packit Service |
1ec7f4 |
uint32_t flags)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list *table_list = NULL;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *chain_list = NULL;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table_list_iter *titer = NULL;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *citer = NULL;
|
|
Packit Service |
1ec7f4 |
struct nftnl_table *table;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *chain;
|
|
Packit Service |
1ec7f4 |
uint32_t table_family, chain_family;
|
|
Packit Service |
1ec7f4 |
bool found = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
table_list = nftnl_table_list_alloc();
|
|
Packit Service |
1ec7f4 |
chain_list = nftnl_chain_list_alloc();
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (xtables_config_parse(filename, table_list, chain_list) < 0) {
|
|
Packit Service |
1ec7f4 |
if (errno == ENOENT) {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"configuration file `%s' does not exists\n",
|
|
Packit Service |
1ec7f4 |
filename);
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"Fatal error parsing config file: %s\n",
|
|
Packit Service |
1ec7f4 |
strerror(errno));
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Stage 1) create tables */
|
|
Packit Service |
1ec7f4 |
titer = nftnl_table_list_iter_create(table_list);
|
|
Packit Service |
1ec7f4 |
while ((table = nftnl_table_list_iter_next(titer)) != NULL) {
|
|
Packit Service |
1ec7f4 |
table_family = nftnl_table_get_u32(table,
|
|
Packit Service |
1ec7f4 |
NFTNL_TABLE_FAMILY);
|
|
Packit Service |
1ec7f4 |
if (h->family != table_family)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
found = true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (batch_table_add(h, NFT_COMPAT_TABLE_ADD, table) < 0) {
|
|
Packit Service |
1ec7f4 |
if (errno == EEXIST) {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"table `%s' already exists, skipping\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"table `%s' cannot be create, reason `%s'. Exitting\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME),
|
|
Packit Service |
1ec7f4 |
strerror(errno));
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags, "table `%s' has been created\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_iter_destroy(titer);
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(table_list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!found)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
/* Stage 2) create chains */
|
|
Packit Service |
1ec7f4 |
citer = nftnl_chain_list_iter_create(chain_list);
|
|
Packit Service |
1ec7f4 |
while ((chain = nftnl_chain_list_iter_next(citer)) != NULL) {
|
|
Packit Service |
1ec7f4 |
chain_family = nftnl_chain_get_u32(chain,
|
|
Packit Service |
1ec7f4 |
NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
if (h->family != chain_family)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, chain) < 0) {
|
|
Packit Service |
1ec7f4 |
if (errno == EEXIST) {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"chain `%s' already exists in table `%s', skipping\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
|
|
Packit Service |
1ec7f4 |
} else {
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"chain `%s' cannot be create, reason `%s'. Exitting\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
|
|
Packit Service |
1ec7f4 |
strerror(errno));
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
xtables_config_perror(flags,
|
|
Packit Service |
1ec7f4 |
"chain `%s' in table `%s' has been created\n",
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
|
|
Packit Service |
1ec7f4 |
(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(citer);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_free(chain_list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->config_done = 1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_free(table_list);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_free(chain_list);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (titer != NULL)
|
|
Packit Service |
1ec7f4 |
nftnl_table_list_iter_destroy(titer);
|
|
Packit Service |
1ec7f4 |
if (citer != NULL)
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(citer);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
h->config_done = -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_xtables_config_load(struct nft_handle *h, const char *filename,
|
|
Packit Service |
1ec7f4 |
uint32_t flags)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
if (!h->config_done)
|
|
Packit Service |
1ec7f4 |
return __nft_xtables_config_load(h, filename, flags);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return h->config_done;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static void nft_chain_zero_rule_counters(struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
const char *table_name;
|
|
Packit Service |
1ec7f4 |
const char *chain_name;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *r;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (r != NULL) {
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr_iter *ei;
|
|
Packit Service |
1ec7f4 |
const char *table_chain;
|
|
Packit Service |
1ec7f4 |
const char *rule_chain;
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *e;
|
|
Packit Service |
1ec7f4 |
bool zero_needed;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
table_chain = nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
if (strcmp(table_chain, table_name))
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
rule_chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
|
|
Packit Service |
1ec7f4 |
if (strcmp(rule_chain, chain_name))
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ei = nftnl_expr_iter_create(r);
|
|
Packit Service |
1ec7f4 |
if (!ei)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
e = nftnl_expr_iter_next(ei);
|
|
Packit Service |
1ec7f4 |
zero_needed = false;
|
|
Packit Service |
1ec7f4 |
while (e != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *en = nftnl_expr_get_str(e, NFTNL_EXPR_NAME);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(en, "counter") == 0 && (
|
|
Packit Service |
1ec7f4 |
nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS) ||
|
|
Packit Service |
1ec7f4 |
nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES))) {
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_PACKETS, 0);
|
|
Packit Service |
1ec7f4 |
nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_BYTES, 0);
|
|
Packit Service |
1ec7f4 |
zero_needed = true;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
e = nftnl_expr_iter_next(ei);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_iter_destroy(ei);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (zero_needed) {
|
|
Packit Service |
1ec7f4 |
/*
|
|
Packit Service |
1ec7f4 |
* Unset RULE_POSITION for older kernels, we want to replace
|
|
Packit Service |
1ec7f4 |
* rule based on its handle only.
|
|
Packit Service |
1ec7f4 |
*/
|
|
Packit Service |
1ec7f4 |
nftnl_rule_unset(r, NFTNL_RULE_POSITION);
|
|
Packit Service |
1ec7f4 |
batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
r = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
|
|
Packit Service |
1ec7f4 |
const char *table, bool verbose)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *c;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
goto err;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (c != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_name =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
const char *chain_table =
|
|
Packit Service |
1ec7f4 |
nftnl_chain_get(c, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, chain_table) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL && strcmp(chain, chain_name) != 0)
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (verbose)
|
|
Packit Service |
1ec7f4 |
fprintf(stdout, "Zeroing chain `%s'\n", chain_name);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
|
|
Packit Service |
1ec7f4 |
/* zero base chain counters. */
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
|
|
Packit Service |
1ec7f4 |
nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nft_chain_zero_rule_counters(h, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (chain != NULL)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
c = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
err:
|
|
Packit Service |
1ec7f4 |
/* the core expects 1 for success and 0 for error */
|
|
Packit Service |
1ec7f4 |
return ret == 0 ? 1 : 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
if (invflags & flag)
|
|
Packit Service |
1ec7f4 |
return NFT_CMP_NEQ;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return NFT_CMP_EQ;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
#define NFT_COMPAT_EXPR_MAX 8
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
|
|
Packit Service |
1ec7f4 |
"match",
|
|
Packit Service |
1ec7f4 |
"target",
|
|
Packit Service |
1ec7f4 |
"payload",
|
|
Packit Service |
1ec7f4 |
"meta",
|
|
Packit Service |
1ec7f4 |
"cmp",
|
|
Packit Service |
1ec7f4 |
"bitwise",
|
|
Packit Service |
1ec7f4 |
"counter",
|
|
Packit Service |
1ec7f4 |
"immediate"
|
|
Packit Service |
1ec7f4 |
};
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_is_expr_compatible(const struct nftnl_expr *expr)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
|
|
Packit Service |
1ec7f4 |
int i;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) {
|
|
Packit Service |
1ec7f4 |
if (strcmp(supported_exprs[i], name) == 0)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!strcmp(name, "limit") &&
|
|
Packit Service |
1ec7f4 |
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_TYPE) == NFT_LIMIT_PKTS &&
|
|
Packit Service |
1ec7f4 |
nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static bool nft_is_rule_compatible(struct nftnl_rule *rule)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_expr *expr;
|
|
Packit Service |
1ec7f4 |
bool compatible = false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_expr_iter_create(rule);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (expr != NULL) {
|
|
Packit Service |
1ec7f4 |
if (nft_is_expr_compatible(expr) == 0) {
|
|
Packit Service |
1ec7f4 |
expr = nftnl_expr_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
compatible = true;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_expr_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return compatible;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_is_chain_compatible(const struct nft_handle *h,
|
|
Packit Service |
1ec7f4 |
const struct nftnl_chain *chain)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
const char *table, *name, *type, *cur_table;
|
|
Packit Service |
1ec7f4 |
struct builtin_chain *chains;
|
|
Packit Service |
1ec7f4 |
int i, j, prio;
|
|
Packit Service |
1ec7f4 |
enum nf_inet_hooks hook;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
|
|
Packit Service |
1ec7f4 |
type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE);
|
|
Packit Service |
1ec7f4 |
prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO);
|
|
Packit Service |
1ec7f4 |
hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (i = 0; i < NFT_TABLE_MAX; i++) {
|
|
Packit Service |
1ec7f4 |
cur_table = h->tables[i].name;
|
|
Packit Service |
1ec7f4 |
chains = h->tables[i].chains;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!cur_table || strcmp(table, cur_table) != 0)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
|
|
Packit Service |
1ec7f4 |
if (strcmp(name, chains[j].name) != 0)
|
|
Packit Service |
1ec7f4 |
continue;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(type, chains[j].type) == 0 &&
|
|
Packit Service |
1ec7f4 |
prio == chains[j].prio &&
|
|
Packit Service |
1ec7f4 |
hook == chains[j].hook)
|
|
Packit Service |
1ec7f4 |
return 0;
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return 1;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_chain *chain;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_chain_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_chain_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return -1;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
chain = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (chain != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *chain_table;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
chain_table = nftnl_chain_get_str(chain, NFTNL_CHAIN_TABLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(chain_table, tablename) ||
|
|
Packit Service |
1ec7f4 |
!nft_chain_builtin(chain))
|
|
Packit Service |
1ec7f4 |
goto next;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = nft_is_chain_compatible(h, chain);
|
|
Packit Service |
1ec7f4 |
if (ret != 0)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next:
|
|
Packit Service |
1ec7f4 |
chain = nftnl_chain_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_chain_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
return ret;
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
bool nft_is_table_compatible(struct nft_handle *h, const char *tablename)
|
|
Packit Service |
1ec7f4 |
{
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list *list;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule_list_iter *iter;
|
|
Packit Service |
1ec7f4 |
struct nftnl_rule *rule;
|
|
Packit Service |
1ec7f4 |
int ret = 0;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (!nft_table_builtin_find(h, tablename))
|
|
Packit Service |
1ec7f4 |
return false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = nft_are_chains_compatible(h, tablename);
|
|
Packit Service |
1ec7f4 |
if (ret != 0)
|
|
Packit Service |
1ec7f4 |
return false;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
list = nft_rule_list_get(h);
|
|
Packit Service |
1ec7f4 |
if (list == NULL)
|
|
Packit Service |
1ec7f4 |
return true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
iter = nftnl_rule_list_iter_create(list);
|
|
Packit Service |
1ec7f4 |
if (iter == NULL)
|
|
Packit Service |
1ec7f4 |
return true;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
rule = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
while (rule != NULL) {
|
|
Packit Service |
1ec7f4 |
const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE);
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
if (strcmp(table, tablename))
|
|
Packit Service |
1ec7f4 |
goto next_rule;
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
ret = nft_is_rule_compatible(rule);
|
|
Packit Service |
1ec7f4 |
if (ret != 0)
|
|
Packit Service |
1ec7f4 |
break;
|
|
Packit Service |
1ec7f4 |
next_rule:
|
|
Packit Service |
1ec7f4 |
rule = nftnl_rule_list_iter_next(iter);
|
|
Packit Service |
1ec7f4 |
}
|
|
Packit Service |
1ec7f4 |
|
|
Packit Service |
1ec7f4 |
nftnl_rule_list_iter_destroy(iter);
|
|
Packit Service |
1ec7f4 |
return ret == 0;
|
|
Packit Service |
1ec7f4 |
}
|