|
Packit |
7b22a4 |
/*
|
|
Packit |
7b22a4 |
* (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit |
7b22a4 |
* (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
7b22a4 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
7b22a4 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
7b22a4 |
* (at your option) any later version.
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This code has been sponsored by Sophos Astaro <http://www.sophos.com>
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <string.h>
|
|
Packit |
7b22a4 |
#include <stdio.h>
|
|
Packit |
7b22a4 |
#include <stdlib.h>
|
|
Packit |
7b22a4 |
#include <stdbool.h>
|
|
Packit |
7b22a4 |
#include <netdb.h>
|
|
Packit |
7b22a4 |
#include <errno.h>
|
|
Packit |
7b22a4 |
#include <inttypes.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <xtables.h>
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
#include <linux/netfilter/nf_tables.h>
|
|
Packit |
7b22a4 |
#include <linux/netfilter/xt_comment.h>
|
|
Packit |
7b22a4 |
#include <linux/netfilter/xt_limit.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <libmnl/libmnl.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/rule.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/expr.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include "nft-shared.h"
|
|
Packit |
7b22a4 |
#include "nft-bridge.h"
|
|
Packit |
7b22a4 |
#include "xshared.h"
|
|
Packit |
7b22a4 |
#include "nft.h"
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
extern struct nft_family_ops nft_family_ops_ipv4;
|
|
Packit |
7b22a4 |
extern struct nft_family_ops nft_family_ops_ipv6;
|
|
Packit |
7b22a4 |
extern struct nft_family_ops nft_family_ops_arp;
|
|
Packit |
7b22a4 |
extern struct nft_family_ops nft_family_ops_bridge;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_meta(struct nftnl_rule *r, uint32_t key)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_alloc("meta");
|
|
Packit |
7b22a4 |
if (expr == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, key);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_META_DREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_alloc("payload");
|
|
Packit |
7b22a4 |
if (expr == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_PAYLOAD_BASE, base);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_PAYLOAD_DREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_PAYLOAD_OFFSET, offset);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_PAYLOAD_LEN, len);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* bitwise operation is = sreg & mask ^ xor */
|
|
Packit |
7b22a4 |
void add_bitwise_u16(struct nftnl_rule *r, uint16_t mask, uint16_t xor)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_alloc("bitwise");
|
|
Packit |
7b22a4 |
if (expr == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_SREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_DREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_LEN, sizeof(uint16_t));
|
|
Packit |
7b22a4 |
nftnl_expr_set(expr, NFTNL_EXPR_BITWISE_MASK, &mask, sizeof(uint16_t));
|
|
Packit |
7b22a4 |
nftnl_expr_set(expr, NFTNL_EXPR_BITWISE_XOR, &xor, sizeof(uint16_t));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
uint32_t xor[4] = { 0 };
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_alloc("bitwise");
|
|
Packit |
7b22a4 |
if (expr == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_SREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_DREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_BITWISE_LEN, len);
|
|
Packit |
7b22a4 |
nftnl_expr_set(expr, NFTNL_EXPR_BITWISE_MASK, mask, len);
|
|
Packit |
7b22a4 |
nftnl_expr_set(expr, NFTNL_EXPR_BITWISE_XOR, &xor, len);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_cmp_ptr(struct nftnl_rule *r, uint32_t op, void *data, size_t len)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_alloc("cmp");
|
|
Packit |
7b22a4 |
if (expr == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_CMP_SREG, NFT_REG_1);
|
|
Packit |
7b22a4 |
nftnl_expr_set_u32(expr, NFTNL_EXPR_CMP_OP, op);
|
|
Packit |
7b22a4 |
nftnl_expr_set(expr, NFTNL_EXPR_CMP_DATA, data, len);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_add_expr(r, expr);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_cmp_u8(struct nftnl_rule *r, uint8_t val, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, &val, sizeof(val));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_cmp_u16(struct nftnl_rule *r, uint16_t val, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, &val, sizeof(val));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_cmp_u32(struct nftnl_rule *r, uint32_t val, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, &val, sizeof(val));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_iniface(struct nftnl_rule *r, char *iface, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int iface_len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
iface_len = strlen(iface);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
add_meta(r, NFT_META_IIFNAME);
|
|
Packit |
7b22a4 |
if (iface[iface_len - 1] == '+') {
|
|
Packit |
7b22a4 |
if (iface_len > 1)
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, iface, iface_len - 1);
|
|
Packit |
7b22a4 |
} else
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, iface, iface_len + 1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_outiface(struct nftnl_rule *r, char *iface, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int iface_len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
iface_len = strlen(iface);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
add_meta(r, NFT_META_OIFNAME);
|
|
Packit |
7b22a4 |
if (iface[iface_len - 1] == '+') {
|
|
Packit |
7b22a4 |
if (iface_len > 1)
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, iface, iface_len - 1);
|
|
Packit |
7b22a4 |
} else
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, iface, iface_len + 1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
void add_addr(struct nftnl_rule *r, int offset,
|
|
Packit |
7b22a4 |
void *data, void *mask, size_t len, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit Service |
635b90 |
const char *m = mask;
|
|
Packit |
7b22a4 |
int i;
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
|
Packit Service |
635b90 |
|
|
Packit |
7b22a4 |
for (i = 0; i < len; i++) {
|
|
Packit Service |
635b90 |
if (m[i] != 0xff)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
if (i != len)
|
|
Packit |
7b22a4 |
add_bitwise(r, mask, len);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
add_cmp_ptr(r, op, data, len);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_proto(struct nftnl_rule *r, int offset, size_t len,
|
|
Packit |
7b22a4 |
uint8_t proto, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER);
|
|
Packit |
7b22a4 |
add_cmp_u8(r, proto, op);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void add_l4proto(struct nftnl_rule *r, uint8_t proto, uint32_t op)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
add_meta(r, NFT_META_L4PROTO);
|
|
Packit |
7b22a4 |
add_cmp_u8(r, proto, op);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
|
|
Packit |
7b22a4 |
unsigned const char *a_iniface_mask,
|
|
Packit |
7b22a4 |
unsigned const char *a_outiface_mask,
|
|
Packit |
7b22a4 |
const char *b_iniface, const char *b_outiface,
|
|
Packit |
7b22a4 |
unsigned const char *b_iniface_mask,
|
|
Packit |
7b22a4 |
unsigned const char *b_outiface_mask)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
int i;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (i = 0; i < IFNAMSIZ; i++) {
|
|
Packit |
7b22a4 |
if (a_iniface_mask[i] != b_iniface_mask[i]) {
|
|
Packit |
7b22a4 |
DEBUGP("different iniface mask %x, %x (%d)\n",
|
|
Packit |
7b22a4 |
a_iniface_mask[i] & 0xff, b_iniface_mask[i] & 0xff, i);
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if ((a_iniface[i] & a_iniface_mask[i])
|
|
Packit |
7b22a4 |
!= (b_iniface[i] & b_iniface_mask[i])) {
|
|
Packit |
7b22a4 |
DEBUGP("different iniface\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (a_outiface_mask[i] != b_outiface_mask[i]) {
|
|
Packit |
7b22a4 |
DEBUGP("different outiface mask\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if ((a_outiface[i] & a_outiface_mask[i])
|
|
Packit |
7b22a4 |
!= (b_outiface[i] & b_outiface_mask[i])) {
|
|
Packit |
7b22a4 |
DEBUGP("different outiface\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned char *mask)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (len == 0)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
memcpy(dst, name, len);
|
|
Packit |
7b22a4 |
if (name[len - 1] == '\0') {
|
|
Packit |
7b22a4 |
if (mask)
|
|
Packit |
7b22a4 |
memset(mask, 0xff, len);
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (len >= IFNAMSIZ)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* wildcard */
|
|
Packit |
7b22a4 |
dst[len++] = '+';
|
|
Packit |
7b22a4 |
if (len >= IFNAMSIZ)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
dst[len++] = 0;
|
|
Packit |
7b22a4 |
if (mask)
|
|
Packit |
7b22a4 |
memset(mask, 0xff, len - 2);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int parse_meta(struct nftnl_expr *e, uint8_t key, char *iniface,
|
|
Packit |
7b22a4 |
unsigned char *iniface_mask, char *outiface,
|
|
Packit |
7b22a4 |
unsigned char *outiface_mask, uint8_t *invflags)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t value;
|
|
Packit |
7b22a4 |
const void *ifname;
|
|
Packit |
7b22a4 |
uint32_t len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch(key) {
|
|
Packit |
7b22a4 |
case NFT_META_IIF:
|
|
Packit |
7b22a4 |
value = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_DATA);
|
|
Packit |
7b22a4 |
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
|
|
Packit |
7b22a4 |
*invflags |= IPT_INV_VIA_IN;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if_indextoname(value, iniface);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
memset(iniface_mask, 0xff, strlen(iniface)+1);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_META_OIF:
|
|
Packit |
7b22a4 |
value = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_DATA);
|
|
Packit |
7b22a4 |
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
|
|
Packit |
7b22a4 |
*invflags |= IPT_INV_VIA_OUT;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if_indextoname(value, outiface);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
memset(outiface_mask, 0xff, strlen(outiface)+1);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_META_BRI_IIFNAME:
|
|
Packit |
7b22a4 |
case NFT_META_IIFNAME:
|
|
Packit |
7b22a4 |
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len;;
|
|
Packit |
7b22a4 |
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
|
|
Packit |
7b22a4 |
*invflags |= IPT_INV_VIA_IN;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
parse_ifname(ifname, len, iniface, iniface_mask);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_META_BRI_OIFNAME:
|
|
Packit |
7b22a4 |
case NFT_META_OIFNAME:
|
|
Packit |
7b22a4 |
ifname = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len;;
|
|
Packit |
7b22a4 |
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
|
|
Packit |
7b22a4 |
*invflags |= IPT_INV_VIA_OUT;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
parse_ifname(ifname, len, outiface, outiface_mask);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
return -1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t tg_len;
|
|
Packit |
7b22a4 |
const char *targname = nftnl_expr_get_str(e, NFTNL_EXPR_TG_NAME);
|
|
Packit |
7b22a4 |
const void *targinfo = nftnl_expr_get(e, NFTNL_EXPR_TG_INFO, &tg_len);
|
|
Packit |
7b22a4 |
struct xtables_target *target;
|
|
Packit |
7b22a4 |
struct xt_entry_target *t;
|
|
Packit |
7b22a4 |
size_t size;
|
|
Packit |
7b22a4 |
void *data = ctx->cs;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
target = xtables_find_target(targname, XTF_TRY_LOAD);
|
|
Packit |
7b22a4 |
if (target == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
t = xtables_calloc(1, size);
|
|
Packit |
7b22a4 |
memcpy(&t->data, targinfo, tg_len);
|
|
Packit |
7b22a4 |
t->u.target_size = size;
|
|
Packit |
7b22a4 |
t->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
|
|
Packit |
7b22a4 |
strcpy(t->u.user.name, target->name);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
target->t = t;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_target(target, data);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t mt_len;
|
|
Packit |
7b22a4 |
const char *mt_name = nftnl_expr_get_str(e, NFTNL_EXPR_MT_NAME);
|
|
Packit |
7b22a4 |
const void *mt_info = nftnl_expr_get(e, NFTNL_EXPR_MT_INFO, &mt_len);
|
|
Packit |
7b22a4 |
struct xtables_match *match;
|
|
Packit |
7b22a4 |
struct xtables_rule_match **matches;
|
|
Packit |
7b22a4 |
struct xt_entry_match *m;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (ctx->h->family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6:
|
|
Packit |
7b22a4 |
case NFPROTO_BRIDGE:
|
|
Packit |
7b22a4 |
matches = &ctx->cs->matches;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n",
|
|
Packit |
7b22a4 |
ctx->h->family);
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
match = xtables_find_match(mt_name, XTF_TRY_LOAD, matches);
|
|
Packit |
7b22a4 |
if (match == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
m = xtables_calloc(1, sizeof(struct xt_entry_match) + mt_len);
|
|
Packit |
7b22a4 |
memcpy(&m->data, mt_info, mt_len);
|
|
Packit |
7b22a4 |
m->u.match_size = mt_len + XT_ALIGN(sizeof(struct xt_entry_match));
|
|
Packit |
7b22a4 |
m->u.user.revision = nftnl_expr_get_u32(e, NFTNL_EXPR_TG_REV);
|
|
Packit |
7b22a4 |
strcpy(m->u.user.name, match->name);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
match->m = m;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (ctx->h->ops->parse_match != NULL)
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_match(match, ctx->cs);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void print_proto(uint16_t proto, int invert)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const struct protoent *pent = getprotobynumber(proto);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (invert)
|
|
Packit |
7b22a4 |
printf("! ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (pent) {
|
|
Packit |
7b22a4 |
printf("-p %s ", pent->p_name);
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("-p %u ", proto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t len;
|
|
Packit |
7b22a4 |
uint8_t op;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
memcpy(data, nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len), dlen);
|
|
Packit |
7b22a4 |
op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
|
|
Packit |
7b22a4 |
if (op == NFT_CMP_NEQ)
|
|
Packit |
7b22a4 |
*inv = true;
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
*inv = false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_target *target;
|
|
Packit |
7b22a4 |
struct xt_entry_target *t;
|
|
Packit |
7b22a4 |
unsigned int size;
|
|
Packit |
7b22a4 |
const char *targname;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (ctx->meta.key) {
|
|
Packit |
7b22a4 |
case NFT_META_NFTRACE:
|
|
Packit |
7b22a4 |
if (ctx->immediate.data[0] == 0)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
targname = "TRACE";
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
target = xtables_find_target(targname, XTF_TRY_LOAD);
|
|
Packit |
7b22a4 |
if (target == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
t = xtables_calloc(1, size);
|
|
Packit |
7b22a4 |
t->u.target_size = size;
|
|
Packit |
7b22a4 |
t->u.user.revision = target->revision;
|
|
Packit |
7b22a4 |
strcpy(t->u.user.name, targname);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
target->t = t;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_target(target, ctx->cs);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
ctx->meta.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG) &&
|
|
Packit |
7b22a4 |
(ctx->flags & NFT_XT_CTX_IMMEDIATE) &&
|
|
Packit |
7b22a4 |
nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG) == ctx->immediate.reg) {
|
|
Packit |
7b22a4 |
ctx->flags &= ~NFT_XT_CTX_IMMEDIATE;
|
|
Packit |
7b22a4 |
nft_meta_set_to_target(ctx);
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
|
|
Packit |
7b22a4 |
ctx->flags |= NFT_XT_CTX_META;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_payload(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
|
|
Packit |
7b22a4 |
memcpy(&ctx->prev_payload, &ctx->payload,
|
|
Packit |
7b22a4 |
sizeof(ctx->prev_payload));
|
|
Packit |
7b22a4 |
ctx->flags |= NFT_XT_CTX_PREV_PAYLOAD;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
|
|
Packit |
7b22a4 |
ctx->payload.base = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_BASE);
|
|
Packit |
7b22a4 |
ctx->payload.offset = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET);
|
|
Packit |
7b22a4 |
ctx->payload.len = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_LEN);
|
|
Packit |
7b22a4 |
ctx->flags |= NFT_XT_CTX_PAYLOAD;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t reg, len;
|
|
Packit |
7b22a4 |
const void *data;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
reg = nftnl_expr_get_u32(e, NFTNL_EXPR_BITWISE_SREG);
|
|
Packit |
7b22a4 |
if (ctx->reg && reg != ctx->reg)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
data = nftnl_expr_get(e, NFTNL_EXPR_BITWISE_XOR, &len;;
|
|
Packit |
7b22a4 |
memcpy(ctx->bitwise.xor, data, len);
|
|
Packit |
7b22a4 |
data = nftnl_expr_get(e, NFTNL_EXPR_BITWISE_MASK, &len;;
|
|
Packit |
7b22a4 |
memcpy(ctx->bitwise.mask, data, len);
|
|
Packit |
7b22a4 |
ctx->flags |= NFT_XT_CTX_BITWISE;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
void *data = ctx->cs;
|
|
Packit |
7b22a4 |
uint32_t reg;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
reg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
|
|
Packit |
7b22a4 |
if (ctx->reg && reg != ctx->reg)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (ctx->flags & NFT_XT_CTX_META) {
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_meta(ctx, e, data);
|
|
Packit |
7b22a4 |
ctx->flags &= ~NFT_XT_CTX_META;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
/* bitwise context is interpreted from payload */
|
|
Packit |
7b22a4 |
if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_payload(ctx, e, data);
|
|
Packit |
7b22a4 |
ctx->flags &= ~NFT_XT_CTX_PAYLOAD;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_counter(struct nftnl_expr *e, struct xt_counters *counters)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
counters->pcnt = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS);
|
|
Packit |
7b22a4 |
counters->bcnt = nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *chain = nftnl_expr_get_str(e, NFTNL_EXPR_IMM_CHAIN);
|
|
Packit |
7b22a4 |
const char *jumpto = NULL;
|
|
Packit |
7b22a4 |
bool nft_goto = false;
|
|
Packit |
7b22a4 |
void *data = ctx->cs;
|
|
Packit |
7b22a4 |
int verdict;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
|
|
Packit |
7b22a4 |
const void *imm_data;
|
|
Packit |
7b22a4 |
uint32_t len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
imm_data = nftnl_expr_get_data(e, NFTNL_EXPR_IMM_DATA, &len;;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (len > sizeof(ctx->immediate.data))
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
memcpy(ctx->immediate.data, imm_data, len);
|
|
Packit |
7b22a4 |
ctx->immediate.len = len;
|
|
Packit |
7b22a4 |
ctx->immediate.reg = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_DREG);
|
|
Packit |
7b22a4 |
ctx->flags |= NFT_XT_CTX_IMMEDIATE;
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
verdict = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_VERDICT);
|
|
Packit |
7b22a4 |
/* Standard target? */
|
|
Packit |
7b22a4 |
switch(verdict) {
|
|
Packit |
7b22a4 |
case NF_ACCEPT:
|
|
Packit |
7b22a4 |
jumpto = "ACCEPT";
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NF_DROP:
|
|
Packit |
7b22a4 |
jumpto = "DROP";
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_RETURN:
|
|
Packit |
7b22a4 |
jumpto = "RETURN";
|
|
Packit |
7b22a4 |
break;;
|
|
Packit |
7b22a4 |
case NFT_GOTO:
|
|
Packit |
7b22a4 |
nft_goto = true;
|
|
Packit |
7b22a4 |
/* fall through */
|
|
Packit |
7b22a4 |
case NFT_JUMP:
|
|
Packit |
7b22a4 |
jumpto = chain;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_immediate(jumpto, nft_goto, data);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
__u32 burst = nftnl_expr_get_u32(e, NFTNL_EXPR_LIMIT_BURST);
|
|
Packit |
7b22a4 |
__u64 unit = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_UNIT);
|
|
Packit |
7b22a4 |
__u64 rate = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_RATE);
|
|
Packit |
7b22a4 |
struct xtables_rule_match **matches;
|
|
Packit |
7b22a4 |
struct xtables_match *match;
|
|
Packit |
7b22a4 |
struct xt_rateinfo *rinfo;
|
|
Packit |
7b22a4 |
size_t size;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (ctx->h->family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6:
|
|
Packit |
7b22a4 |
case NFPROTO_BRIDGE:
|
|
Packit |
7b22a4 |
matches = &ctx->cs->matches;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr, "BUG: nft_parse_limit() unknown family %d\n",
|
|
Packit |
7b22a4 |
ctx->h->family);
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
match = xtables_find_match("limit", XTF_TRY_LOAD, matches);
|
|
Packit |
7b22a4 |
if (match == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
|
|
Packit |
7b22a4 |
match->m = xtables_calloc(1, size);
|
|
Packit |
7b22a4 |
match->m->u.match_size = size;
|
|
Packit |
7b22a4 |
strcpy(match->m->u.user.name, match->name);
|
|
Packit |
7b22a4 |
match->m->u.user.revision = match->revision;
|
|
Packit |
7b22a4 |
xs_init_match(match);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
rinfo = (void *)match->m->data;
|
|
Packit |
7b22a4 |
rinfo->avg = XT_LIMIT_SCALE * unit / rate;
|
|
Packit |
7b22a4 |
rinfo->burst = burst;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (ctx->h->ops->parse_match != NULL)
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_match(match, ctx->cs);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void nft_parse_lookup(struct nft_xt_ctx *ctx, struct nft_handle *h,
|
|
Packit |
7b22a4 |
struct nftnl_expr *e)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (ctx->h->ops->parse_lookup)
|
|
Packit |
7b22a4 |
ctx->h->ops->parse_lookup(ctx, e, NULL);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void nft_rule_to_iptables_command_state(struct nft_handle *h,
|
|
Packit |
7b22a4 |
const struct nftnl_rule *r,
|
|
Packit |
7b22a4 |
struct iptables_command_state *cs)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_expr_iter *iter;
|
|
Packit |
7b22a4 |
struct nftnl_expr *expr;
|
|
Packit |
7b22a4 |
struct nft_xt_ctx ctx = {
|
|
Packit |
7b22a4 |
.cs = cs,
|
|
Packit |
7b22a4 |
.h = h,
|
|
Packit |
7b22a4 |
.table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE),
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
iter = nftnl_expr_iter_create(r);
|
|
Packit |
7b22a4 |
if (iter == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ctx.iter = iter;
|
|
Packit |
7b22a4 |
expr = nftnl_expr_iter_next(iter);
|
|
Packit |
7b22a4 |
while (expr != NULL) {
|
|
Packit |
7b22a4 |
const char *name =
|
|
Packit |
7b22a4 |
nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(name, "counter") == 0)
|
|
Packit |
7b22a4 |
nft_parse_counter(expr, &ctx.cs->counters);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "payload") == 0)
|
|
Packit |
7b22a4 |
nft_parse_payload(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "meta") == 0)
|
|
Packit |
7b22a4 |
nft_parse_meta(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "bitwise") == 0)
|
|
Packit |
7b22a4 |
nft_parse_bitwise(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "cmp") == 0)
|
|
Packit |
7b22a4 |
nft_parse_cmp(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "immediate") == 0)
|
|
Packit |
7b22a4 |
nft_parse_immediate(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "match") == 0)
|
|
Packit |
7b22a4 |
nft_parse_match(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "target") == 0)
|
|
Packit |
7b22a4 |
nft_parse_target(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "limit") == 0)
|
|
Packit |
7b22a4 |
nft_parse_limit(&ctx, expr);
|
|
Packit |
7b22a4 |
else if (strcmp(name, "lookup") == 0)
|
|
Packit |
7b22a4 |
nft_parse_lookup(&ctx, h, expr);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
expr = nftnl_expr_iter_next(iter);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_expr_iter_destroy(iter);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) {
|
|
Packit |
7b22a4 |
const void *data;
|
|
Packit |
7b22a4 |
uint32_t len, size;
|
|
Packit |
7b22a4 |
const char *comment;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len;;
|
|
Packit |
7b22a4 |
comment = get_comment(data, len);
|
|
Packit |
7b22a4 |
if (comment) {
|
|
Packit |
7b22a4 |
struct xtables_match *match;
|
|
Packit |
7b22a4 |
struct xt_entry_match *m;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
match = xtables_find_match("comment", XTF_TRY_LOAD,
|
|
Packit |
7b22a4 |
&cs->matches);
|
|
Packit |
7b22a4 |
if (match == NULL)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
size = XT_ALIGN(sizeof(struct xt_entry_match))
|
|
Packit |
7b22a4 |
+ match->size;
|
|
Packit |
7b22a4 |
m = xtables_calloc(1, size);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
strncpy((char *)m->data, comment, match->size - 1);
|
|
Packit |
7b22a4 |
m->u.match_size = size;
|
|
Packit |
7b22a4 |
m->u.user.revision = 0;
|
|
Packit |
7b22a4 |
strcpy(m->u.user.name, match->name);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
match->m = m;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cs->target != NULL) {
|
|
Packit |
7b22a4 |
cs->jumpto = cs->target->name;
|
|
Packit |
7b22a4 |
} else if (cs->jumpto != NULL) {
|
|
Packit |
7b22a4 |
struct xt_entry_target *t;
|
|
Packit |
7b22a4 |
uint32_t size;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
|
|
Packit |
7b22a4 |
if (!cs->target)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
|
|
Packit |
7b22a4 |
t = xtables_calloc(1, size);
|
|
Packit |
7b22a4 |
t->u.target_size = size;
|
|
Packit |
7b22a4 |
t->u.user.revision = cs->target->revision;
|
|
Packit |
7b22a4 |
strcpy(t->u.user.name, cs->jumpto);
|
|
Packit |
7b22a4 |
cs->target->t = t;
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
cs->jumpto = "";
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void nft_clear_iptables_command_state(struct iptables_command_state *cs)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
xtables_rule_matches_free(&cs->matches);
|
|
Packit |
7b22a4 |
if (cs->target) {
|
|
Packit |
7b22a4 |
free(cs->target->t);
|
|
Packit |
7b22a4 |
cs->target->t = NULL;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cs->target == cs->target->next) {
|
|
Packit |
7b22a4 |
free(cs->target);
|
|
Packit |
7b22a4 |
cs->target = NULL;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void print_header(unsigned int format, const char *chain, const char *pol,
|
|
Packit |
7b22a4 |
const struct xt_counters *counters, bool basechain,
|
|
Packit |
7b22a4 |
uint32_t refs, uint32_t entries)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
printf("Chain %s", chain);
|
|
Packit |
7b22a4 |
if (basechain) {
|
|
Packit |
7b22a4 |
printf(" (policy %s", pol);
|
|
Packit |
7b22a4 |
if (!(format & FMT_NOCOUNTS)) {
|
|
Packit |
7b22a4 |
fputc(' ', stdout);
|
|
Packit |
7b22a4 |
xtables_print_num(counters->pcnt, (format|FMT_NOTABLE));
|
|
Packit |
7b22a4 |
fputs("packets, ", stdout);
|
|
Packit |
7b22a4 |
xtables_print_num(counters->bcnt, (format|FMT_NOTABLE));
|
|
Packit |
7b22a4 |
fputs("bytes", stdout);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
printf(")\n");
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
printf(" (%u references)\n", refs);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (format & FMT_LINENUMBERS)
|
|
Packit |
7b22a4 |
printf(FMT("%-4s ", "%s "), "num");
|
|
Packit |
7b22a4 |
if (!(format & FMT_NOCOUNTS)) {
|
|
Packit |
7b22a4 |
if (format & FMT_KILOMEGAGIGA) {
|
|
Packit |
7b22a4 |
printf(FMT("%5s ","%s "), "pkts");
|
|
Packit |
7b22a4 |
printf(FMT("%5s ","%s "), "bytes");
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
printf(FMT("%8s ","%s "), "pkts");
|
|
Packit |
7b22a4 |
printf(FMT("%10s ","%s "), "bytes");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (!(format & FMT_NOTARGET))
|
|
Packit |
7b22a4 |
printf(FMT("%-9s ","%s "), "target");
|
|
Packit |
7b22a4 |
fputs(" prot ", stdout);
|
|
Packit |
7b22a4 |
if (format & FMT_OPTIONS)
|
|
Packit |
7b22a4 |
fputs("opt", stdout);
|
|
Packit |
7b22a4 |
if (format & FMT_VIA) {
|
|
Packit |
7b22a4 |
printf(FMT(" %-6s ","%s "), "in");
|
|
Packit |
7b22a4 |
printf(FMT("%-6s ","%s "), "out");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
printf(FMT(" %-19s ","%s "), "source");
|
|
Packit |
7b22a4 |
printf(FMT(" %-19s "," %s "), "destination");
|
|
Packit |
7b22a4 |
printf("\n");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void print_rule_details(const struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
const char *targname, uint8_t flags,
|
|
Packit |
7b22a4 |
uint8_t invflags, uint8_t proto,
|
|
Packit |
7b22a4 |
unsigned int num, unsigned int format)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (format & FMT_LINENUMBERS)
|
|
Packit |
7b22a4 |
printf(FMT("%-4u ", "%u "), num);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!(format & FMT_NOCOUNTS)) {
|
|
Packit |
7b22a4 |
xtables_print_num(cs->counters.pcnt, format);
|
|
Packit |
7b22a4 |
xtables_print_num(cs->counters.bcnt, format);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!(format & FMT_NOTARGET))
|
|
Packit |
7b22a4 |
printf(FMT("%-9s ", "%s "), targname ? targname : "");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
fputc(invflags & XT_INV_PROTO ? '!' : ' ', stdout);
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *pname =
|
|
Packit |
7b22a4 |
proto_to_name(proto, format&FMT_NUMERIC);
|
|
Packit |
7b22a4 |
if (pname)
|
|
Packit |
7b22a4 |
printf(FMT("%-5s", "%s "), pname);
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
printf(FMT("%-5hu", "%hu "), proto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void
|
|
Packit |
7b22a4 |
print_iface(char letter, const char *iface, const unsigned char *mask, int inv)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
unsigned int i;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (mask[0] == 0)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("%s-%c ", inv ? "! " : "", letter);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (i = 0; i < IFNAMSIZ; i++) {
|
|
Packit |
7b22a4 |
if (mask[i] != 0) {
|
|
Packit |
7b22a4 |
if (iface[i] != '\0')
|
|
Packit |
7b22a4 |
printf("%c", iface[i]);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
if (iface[i-1] != '\0')
|
|
Packit |
7b22a4 |
printf("+");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf(" ");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void save_rule_details(const struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
uint8_t invflags, uint16_t proto,
|
|
Packit |
7b22a4 |
const char *iniface,
|
|
Packit |
7b22a4 |
unsigned const char *iniface_mask,
|
|
Packit |
7b22a4 |
const char *outiface,
|
|
Packit |
7b22a4 |
unsigned const char *outiface_mask)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (iniface != NULL) {
|
|
Packit |
7b22a4 |
print_iface('i', iniface, iniface_mask,
|
|
Packit |
7b22a4 |
invflags & IPT_INV_VIA_IN);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (outiface != NULL) {
|
|
Packit |
7b22a4 |
print_iface('o', outiface, outiface_mask,
|
|
Packit |
7b22a4 |
invflags & IPT_INV_VIA_OUT);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (proto > 0) {
|
|
Packit |
7b22a4 |
const struct protoent *pent = getprotobynumber(proto);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (invflags & XT_INV_PROTO)
|
|
Packit |
7b22a4 |
printf("! ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (pent)
|
|
Packit |
7b22a4 |
printf("-p %s ", pent->p_name);
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
printf("-p %u ", proto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void save_counters(const void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const struct iptables_command_state *cs = data;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("[%llu:%llu] ", (unsigned long long)cs->counters.pcnt,
|
|
Packit |
7b22a4 |
(unsigned long long)cs->counters.bcnt);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit |
7b22a4 |
uint64_t pkts = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS);
|
|
Packit |
7b22a4 |
uint64_t bytes = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf(":%s %s [%"PRIu64":%"PRIu64"]\n",
|
|
Packit |
7b22a4 |
chain, policy ?: "-", pkts, bytes);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void save_matches_and_target(const struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
bool goto_flag, const void *fw,
|
|
Packit |
7b22a4 |
unsigned int format)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_rule_match *matchp;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (matchp = cs->matches; matchp; matchp = matchp->next) {
|
|
Packit |
7b22a4 |
if (matchp->match->alias) {
|
|
Packit |
7b22a4 |
printf("-m %s",
|
|
Packit |
7b22a4 |
matchp->match->alias(matchp->match->m));
|
|
Packit |
7b22a4 |
} else
|
|
Packit |
7b22a4 |
printf("-m %s", matchp->match->name);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (matchp->match->save != NULL) {
|
|
Packit |
7b22a4 |
/* cs->fw union makes the trick */
|
|
Packit |
7b22a4 |
matchp->match->save(fw, matchp->match->m);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
printf(" ");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if ((format & (FMT_NOCOUNTS | FMT_C_COUNTS)) == FMT_C_COUNTS)
|
|
Packit |
7b22a4 |
printf("-c %llu %llu ",
|
|
Packit |
7b22a4 |
(unsigned long long)cs->counters.pcnt,
|
|
Packit |
7b22a4 |
(unsigned long long)cs->counters.bcnt);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cs->target != NULL) {
|
|
Packit |
7b22a4 |
if (cs->target->alias) {
|
|
Packit |
7b22a4 |
printf("-j %s", cs->target->alias(cs->target->t));
|
|
Packit |
7b22a4 |
} else
|
|
Packit |
7b22a4 |
printf("-j %s", cs->jumpto);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cs->target->save != NULL)
|
|
Packit |
7b22a4 |
cs->target->save(fw, cs->target->t);
|
|
Packit |
7b22a4 |
} else if (strlen(cs->jumpto) > 0) {
|
|
Packit |
7b22a4 |
printf("-%c %s", goto_flag ? 'g' : 'j', cs->jumpto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("\n");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void print_matches_and_target(struct iptables_command_state *cs,
|
|
Packit |
7b22a4 |
unsigned int format)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_rule_match *matchp;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (matchp = cs->matches; matchp; matchp = matchp->next) {
|
|
Packit |
7b22a4 |
if (matchp->match->print != NULL) {
|
|
Packit |
7b22a4 |
matchp->match->print(&cs->fw, matchp->match->m,
|
|
Packit |
7b22a4 |
format & FMT_NUMERIC);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cs->target != NULL) {
|
|
Packit |
7b22a4 |
if (cs->target->print != NULL) {
|
|
Packit |
7b22a4 |
cs->target->print(&cs->fw, cs->target->t,
|
|
Packit |
7b22a4 |
format & FMT_NUMERIC);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
struct nft_family_ops *nft_family_ops_lookup(int family)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case AF_INET:
|
|
Packit |
7b22a4 |
return &nft_family_ops_ipv4;
|
|
Packit |
7b22a4 |
case AF_INET6:
|
|
Packit |
7b22a4 |
return &nft_family_ops_ipv6;
|
|
Packit |
7b22a4 |
case NFPROTO_ARP:
|
|
Packit |
7b22a4 |
return &nft_family_ops_arp;
|
|
Packit |
7b22a4 |
case NFPROTO_BRIDGE:
|
|
Packit |
7b22a4 |
return &nft_family_ops_bridge;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return NULL;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
bool compare_matches(struct xtables_rule_match *mt1,
|
|
Packit |
7b22a4 |
struct xtables_rule_match *mt2)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct xtables_rule_match *mp1;
|
|
Packit |
7b22a4 |
struct xtables_rule_match *mp2;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
for (mp1 = mt1, mp2 = mt2; mp1 && mp2; mp1 = mp1->next, mp2 = mp2->next) {
|
|
Packit |
7b22a4 |
struct xt_entry_match *m1 = mp1->match->m;
|
|
Packit |
7b22a4 |
struct xt_entry_match *m2 = mp2->match->m;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(m1->u.user.name, m2->u.user.name) != 0) {
|
|
Packit |
7b22a4 |
DEBUGP("mismatching match name\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (m1->u.user.match_size != m2->u.user.match_size) {
|
|
Packit |
7b22a4 |
DEBUGP("mismatching match size\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (memcmp(m1->data, m2->data,
|
|
Packit |
7b22a4 |
mp1->match->userspacesize) != 0) {
|
|
Packit |
7b22a4 |
DEBUGP("mismatch match data\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* Both cursors should be NULL */
|
|
Packit |
7b22a4 |
if (mp1 != mp2) {
|
|
Packit |
7b22a4 |
DEBUGP("mismatch matches amount\n");
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
bool compare_targets(struct xtables_target *tg1, struct xtables_target *tg2)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
if (tg1 == NULL && tg2 == NULL)
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (tg1 == NULL || tg2 == NULL)
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
if (tg1->userspacesize != tg2->userspacesize)
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(tg1->t->u.user.name, tg2->t->u.user.name) != 0)
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (memcmp(tg1->t->data, tg2->t->data, tg1->userspacesize) != 0)
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void nft_ipv46_parse_target(struct xtables_target *t, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct iptables_command_state *cs = data;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
cs->target = t;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
bool nft_ipv46_rule_find(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct iptables_command_state *cs = data, this = {};
|
|
Packit |
7b22a4 |
bool ret = false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_rule_to_iptables_command_state(h, r, &this;;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
DEBUGP("comparing with... ");
|
|
Packit |
7b22a4 |
#ifdef DEBUG_DEL
|
|
Packit |
7b22a4 |
nft_rule_print_save(r, NFT_RULE_APPEND, 0);
|
|
Packit |
7b22a4 |
#endif
|
|
Packit |
7b22a4 |
if (!h->ops->is_same(cs, &this))
|
|
Packit |
7b22a4 |
goto out;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!compare_matches(cs->matches, this.matches)) {
|
|
Packit |
7b22a4 |
DEBUGP("Different matches\n");
|
|
Packit |
7b22a4 |
goto out;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!compare_targets(cs->target, this.target)) {
|
|
Packit |
7b22a4 |
DEBUGP("Different target\n");
|
|
Packit |
7b22a4 |
goto out;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strcmp(cs->jumpto, this.jumpto) != 0) {
|
|
Packit |
7b22a4 |
DEBUGP("Different verdict\n");
|
|
Packit |
7b22a4 |
goto out;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = true;
|
|
Packit |
7b22a4 |
out:
|
|
Packit |
7b22a4 |
h->ops->clear_cs(&this;;
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void nft_check_xt_legacy(int family, bool is_ipt_save)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
static const char tables6[] = "/proc/net/ip6_tables_names";
|
|
Packit |
7b22a4 |
static const char tables4[] = "/proc/net/ip_tables_names";
|
|
Packit |
7b22a4 |
const char *prefix = "ip";
|
|
Packit |
7b22a4 |
FILE *fp = NULL;
|
|
Packit |
7b22a4 |
char buf[1024];
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
fp = fopen(tables4, "r");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6:
|
|
Packit |
7b22a4 |
fp = fopen(tables6, "r");
|
|
Packit |
7b22a4 |
prefix = "ip6";
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!fp)
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (fgets(buf, sizeof(buf), fp))
|
|
Packit |
7b22a4 |
fprintf(stderr, "# Warning: %stables-legacy tables present, use %stables-legacy%s to see them\n",
|
|
Packit |
7b22a4 |
prefix, prefix, is_ipt_save ? "-save" : "");
|
|
Packit |
7b22a4 |
fclose(fp);
|
|
Packit |
7b22a4 |
}
|