|
Packit Service |
d1fe03 |
/*
|
|
Packit Service |
d1fe03 |
* (C) 2013 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit Service |
d1fe03 |
* (C) 2013 by Giuseppe Longo <giuseppelng@gmail.com>
|
|
Packit Service |
d1fe03 |
*
|
|
Packit Service |
d1fe03 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
d1fe03 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
d1fe03 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
d1fe03 |
* (at your option) any later version.
|
|
Packit Service |
d1fe03 |
*
|
|
Packit Service |
d1fe03 |
* This code has been sponsored by Sophos Astaro <http://www.sophos.com>
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
#include <stdio.h>
|
|
Packit Service |
d1fe03 |
#include <stdlib.h>
|
|
Packit Service |
d1fe03 |
#include <string.h>
|
|
Packit Service |
d1fe03 |
#include <netdb.h>
|
|
Packit Service |
d1fe03 |
#include <net/if_arp.h>
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
#include <xtables.h>
|
|
Packit Service |
d1fe03 |
#include <libiptc/libxtc.h>
|
|
Packit Service |
d1fe03 |
#include <net/if_arp.h>
|
|
Packit Service |
d1fe03 |
#include <netinet/if_ether.h>
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
#include <linux/netfilter_arp/arp_tables.h>
|
|
Packit Service |
d1fe03 |
#include <linux/netfilter/nf_tables.h>
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
#include "nft-shared.h"
|
|
Packit Service |
d1fe03 |
#include "nft-arp.h"
|
|
Packit Service |
d1fe03 |
#include "nft.h"
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* a few names */
|
|
Packit Service |
d1fe03 |
char *arp_opcodes[] =
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
"Request",
|
|
Packit Service |
d1fe03 |
"Reply",
|
|
Packit Service |
d1fe03 |
"Request_Reverse",
|
|
Packit Service |
d1fe03 |
"Reply_Reverse",
|
|
Packit Service |
d1fe03 |
"DRARP_Request",
|
|
Packit Service |
d1fe03 |
"DRARP_Reply",
|
|
Packit Service |
d1fe03 |
"DRARP_Error",
|
|
Packit Service |
d1fe03 |
"InARP_Request",
|
|
Packit Service |
d1fe03 |
"ARP_NAK",
|
|
Packit Service |
d1fe03 |
};
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static char *
|
|
Packit Service |
d1fe03 |
addr_to_dotted(const struct in_addr *addrp)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
static char buf[20];
|
|
Packit Service |
d1fe03 |
const unsigned char *bytep;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
bytep = (const unsigned char *) &(addrp->s_addr);
|
|
Packit Service |
d1fe03 |
sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
|
|
Packit Service |
d1fe03 |
return buf;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static char *
|
|
Packit Service |
d1fe03 |
addr_to_host(const struct in_addr *addr)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct hostent *host;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if ((host = gethostbyaddr((char *) addr,
|
|
Packit Service |
d1fe03 |
sizeof(struct in_addr), AF_INET)) != NULL)
|
|
Packit Service |
d1fe03 |
return (char *) host->h_name;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return (char *) NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static char *
|
|
Packit Service |
d1fe03 |
addr_to_network(const struct in_addr *addr)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct netent *net;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL)
|
|
Packit Service |
d1fe03 |
return (char *) net->n_name;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return (char *) NULL;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static char *
|
|
Packit Service |
d1fe03 |
addr_to_anyname(const struct in_addr *addr)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
char *name;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if ((name = addr_to_host(addr)) != NULL ||
|
|
Packit Service |
d1fe03 |
(name = addr_to_network(addr)) != NULL)
|
|
Packit Service |
d1fe03 |
return name;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return addr_to_dotted(addr);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static char *
|
|
Packit Service |
d1fe03 |
mask_to_dotted(const struct in_addr *mask)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
static char buf[22];
|
|
Packit Service |
d1fe03 |
u_int32_t maskaddr, bits;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
maskaddr = ntohl(mask->s_addr);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (maskaddr == 0xFFFFFFFFL)
|
|
Packit Service |
d1fe03 |
/* we don't want to see "/32" */
|
|
Packit Service |
d1fe03 |
return "";
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
i = 32;
|
|
Packit Service |
d1fe03 |
bits = 0xFFFFFFFEL;
|
|
Packit Service |
d1fe03 |
while (--i >= 0 && maskaddr != bits)
|
|
Packit Service |
d1fe03 |
bits <<= 1;
|
|
Packit Service |
d1fe03 |
if (i >= 0)
|
|
Packit Service |
d1fe03 |
sprintf(buf, "/%d", i);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
/* mask was not a decent combination of 1's and 0's */
|
|
Packit Service |
d1fe03 |
snprintf(buf, sizeof(buf), "/%s", addr_to_dotted(mask));
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return buf;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static bool need_devaddr(struct arpt_devaddr_info *info)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; i < ETH_ALEN; i++) {
|
|
Packit Service |
d1fe03 |
if (info->addr[i] || info->mask[i])
|
|
Packit Service |
d1fe03 |
return true;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return false;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
struct arpt_entry *fw = &cs->arp;
|
|
Packit Service |
d1fe03 |
uint32_t op;
|
|
Packit Service |
d1fe03 |
int ret = 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.iniface[0] != '\0') {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_VIA_IN);
|
|
Packit Service |
d1fe03 |
add_iniface(r, fw->arp.iniface, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.outiface[0] != '\0') {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_VIA_OUT);
|
|
Packit Service |
d1fe03 |
add_outiface(r, fw->arp.outiface, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhrd != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_ARPHRD) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHRD);
|
|
Packit Service |
d1fe03 |
add_payload(r, offsetof(struct arphdr, ar_hrd), 2,
|
|
Packit Service |
d1fe03 |
NFT_PAYLOAD_NETWORK_HEADER);
|
|
Packit Service |
d1fe03 |
add_cmp_u16(r, fw->arp.arhrd, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpro != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_ARPPRO) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPPRO);
|
|
Packit Service |
d1fe03 |
add_payload(r, offsetof(struct arphdr, ar_pro), 2,
|
|
Packit Service |
d1fe03 |
NFT_PAYLOAD_NETWORK_HEADER);
|
|
Packit Service |
d1fe03 |
add_cmp_u16(r, fw->arp.arpro, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhln != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_ARPHLN) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPHLN);
|
|
Packit Service |
d1fe03 |
add_proto(r, offsetof(struct arphdr, ar_hln), 1,
|
|
Packit Service |
d1fe03 |
fw->arp.arhln, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
add_proto(r, offsetof(struct arphdr, ar_pln), 1, 4, NFT_CMP_EQ);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpop != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_ARPOP) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_ARPOP);
|
|
Packit Service |
d1fe03 |
add_payload(r, offsetof(struct arphdr, ar_op), 2,
|
|
Packit Service |
d1fe03 |
NFT_PAYLOAD_NETWORK_HEADER);
|
|
Packit Service |
d1fe03 |
add_cmp_u16(r, fw->arp.arpop, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (need_devaddr(&fw->arp.src_devaddr)) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCDEVADDR);
|
|
Packit Service |
d1fe03 |
add_addr(r, sizeof(struct arphdr),
|
|
Packit Service |
d1fe03 |
&fw->arp.src_devaddr.addr,
|
|
Packit Service |
d1fe03 |
&fw->arp.src_devaddr.mask,
|
|
Packit Service |
d1fe03 |
fw->arp.arhln, op);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.src.s_addr != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.smsk.s_addr != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_SRCIP) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_SRCIP);
|
|
Packit Service |
d1fe03 |
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln,
|
|
Packit Service |
d1fe03 |
&fw->arp.src.s_addr, &fw->arp.smsk.s_addr,
|
|
Packit Service |
d1fe03 |
sizeof(struct in_addr), op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (need_devaddr(&fw->arp.tgt_devaddr)) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTDEVADDR);
|
|
Packit Service |
d1fe03 |
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr),
|
|
Packit Service |
d1fe03 |
&fw->arp.tgt_devaddr.addr,
|
|
Packit Service |
d1fe03 |
&fw->arp.tgt_devaddr.mask,
|
|
Packit Service |
d1fe03 |
fw->arp.arhln, op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.tgt.s_addr != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.tmsk.s_addr != 0 ||
|
|
Packit Service |
d1fe03 |
fw->arp.invflags & ARPT_INV_TGTIP) {
|
|
Packit Service |
d1fe03 |
op = nft_invflags2cmp(fw->arp.invflags, ARPT_INV_TGTIP);
|
|
Packit Service |
d1fe03 |
add_addr(r, sizeof(struct arphdr) + fw->arp.arhln + sizeof(struct in_addr) + fw->arp.arhln,
|
|
Packit Service |
d1fe03 |
&fw->arp.tgt.s_addr, &fw->arp.tmsk.s_addr,
|
|
Packit Service |
d1fe03 |
sizeof(struct in_addr), op);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Counters need to me added before the target, otherwise they are
|
|
Packit Service |
d1fe03 |
* increased for each rule because of the way nf_tables works.
|
|
Packit Service |
d1fe03 |
*/
|
|
Packit Service |
d1fe03 |
if (add_counters(r, fw->counters.pcnt, fw->counters.bcnt) < 0)
|
|
Packit Service |
d1fe03 |
return -1;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (cs->target != NULL) {
|
|
Packit Service |
d1fe03 |
/* Standard target? */
|
|
Packit Service |
d1fe03 |
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
|
|
Packit Service |
d1fe03 |
ret = add_verdict(r, NF_ACCEPT);
|
|
Packit Service |
d1fe03 |
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
|
|
Packit Service |
d1fe03 |
ret = add_verdict(r, NF_DROP);
|
|
Packit Service |
d1fe03 |
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
|
|
Packit Service |
d1fe03 |
ret = add_verdict(r, NFT_RETURN);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
ret = add_target(r, cs->target->t);
|
|
Packit Service |
d1fe03 |
} else if (strlen(cs->jumpto) > 0) {
|
|
Packit Service |
d1fe03 |
/* No goto in arptables */
|
|
Packit Service |
d1fe03 |
ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return ret;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static uint16_t ipt_to_arpt_flags(uint8_t invflags)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
uint16_t result = 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (invflags & IPT_INV_VIA_IN)
|
|
Packit Service |
d1fe03 |
result |= ARPT_INV_VIA_IN;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (invflags & IPT_INV_VIA_OUT)
|
|
Packit Service |
d1fe03 |
result |= ARPT_INV_VIA_OUT;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (invflags & IPT_INV_SRCIP)
|
|
Packit Service |
d1fe03 |
result |= ARPT_INV_SRCIP;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (invflags & IPT_INV_DSTIP)
|
|
Packit Service |
d1fe03 |
result |= ARPT_INV_TGTIP;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (invflags & IPT_INV_PROTO)
|
|
Packit Service |
d1fe03 |
result |= ARPT_INV_ARPPRO;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return result;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
|
|
Packit Service |
d1fe03 |
void *data)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
struct arpt_entry *fw = &cs->arp;
|
|
Packit Service |
d1fe03 |
uint8_t flags = 0;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
parse_meta(e, ctx->meta.key, fw->arp.iniface, fw->arp.iniface_mask,
|
|
Packit Service |
d1fe03 |
fw->arp.outiface, fw->arp.outiface_mask,
|
|
Packit Service |
d1fe03 |
&flags);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ipt_to_arpt_flags(flags);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_parse_immediate(const char *jumpto, bool nft_goto,
|
|
Packit Service |
d1fe03 |
void *data)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
cs->jumpto = jumpto;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
mask->s_addr = ctx->bitwise.mask[0];
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
|
|
Packit Service |
d1fe03 |
struct nftnl_expr *e,
|
|
Packit Service |
d1fe03 |
struct arpt_devaddr_info *info)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
uint32_t hlen;
|
|
Packit Service |
d1fe03 |
bool inv;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &hlen);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (hlen != ETH_ALEN)
|
|
Packit Service |
d1fe03 |
return false;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, info->addr, ETH_ALEN, &inv;;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (ctx->flags & NFT_XT_CTX_BITWISE) {
|
|
Packit Service |
d1fe03 |
memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
|
|
Packit Service |
d1fe03 |
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
memset(info->mask, 0xff, ETH_ALEN);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return inv;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
|
|
Packit Service |
d1fe03 |
struct nftnl_expr *e, void *data)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
struct arpt_entry *fw = &cs->arp;
|
|
Packit Service |
d1fe03 |
struct in_addr addr;
|
|
Packit Service |
d1fe03 |
uint16_t ar_hrd, ar_pro, ar_op;
|
|
Packit Service |
d1fe03 |
uint8_t ar_hln;
|
|
Packit Service |
d1fe03 |
bool inv;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
switch (ctx->payload.offset) {
|
|
Packit Service |
d1fe03 |
case offsetof(struct arphdr, ar_hrd):
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &ar_hrd, sizeof(ar_hrd), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.arhrd = ar_hrd;
|
|
Packit Service |
d1fe03 |
fw->arp.arhrd_mask = 0xffff;
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_ARPHRD;
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
case offsetof(struct arphdr, ar_pro):
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &ar_pro, sizeof(ar_pro), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.arpro = ar_pro;
|
|
Packit Service |
d1fe03 |
fw->arp.arpro_mask = 0xffff;
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_ARPPRO;
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
case offsetof(struct arphdr, ar_op):
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &ar_op, sizeof(ar_op), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.arpop = ar_op;
|
|
Packit Service |
d1fe03 |
fw->arp.arpop_mask = 0xffff;
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_ARPOP;
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
case offsetof(struct arphdr, ar_hln):
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &ar_hln, sizeof(ar_hln), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.arhln = ar_hln;
|
|
Packit Service |
d1fe03 |
fw->arp.arhln_mask = 0xff;
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_ARPOP;
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
default:
|
|
Packit Service |
d1fe03 |
if (ctx->payload.offset == sizeof(struct arphdr)) {
|
|
Packit Service |
d1fe03 |
if (nft_arp_parse_devaddr(ctx, e, &fw->arp.src_devaddr))
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_SRCDEVADDR;
|
|
Packit Service |
d1fe03 |
} else if (ctx->payload.offset == sizeof(struct arphdr) +
|
|
Packit Service |
d1fe03 |
fw->arp.arhln) {
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &addr, sizeof(addr), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.src.s_addr = addr.s_addr;
|
|
Packit Service |
d1fe03 |
if (ctx->flags & NFT_XT_CTX_BITWISE) {
|
|
Packit Service |
d1fe03 |
parse_mask_ipv4(ctx, &fw->arp.smsk);
|
|
Packit Service |
d1fe03 |
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
fw->arp.smsk.s_addr = 0xffffffff;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_SRCIP;
|
|
Packit Service |
d1fe03 |
} else if (ctx->payload.offset == sizeof(struct arphdr) +
|
|
Packit Service |
d1fe03 |
fw->arp.arhln +
|
|
Packit Service |
d1fe03 |
sizeof(struct in_addr)) {
|
|
Packit Service |
d1fe03 |
if (nft_arp_parse_devaddr(ctx, e, &fw->arp.tgt_devaddr))
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_TGTDEVADDR;
|
|
Packit Service |
d1fe03 |
} else if (ctx->payload.offset == sizeof(struct arphdr) +
|
|
Packit Service |
d1fe03 |
fw->arp.arhln +
|
|
Packit Service |
d1fe03 |
sizeof(struct in_addr) +
|
|
Packit Service |
d1fe03 |
fw->arp.arhln) {
|
|
Packit Service |
d1fe03 |
get_cmp_data(e, &addr, sizeof(addr), &inv;;
|
|
Packit Service |
d1fe03 |
fw->arp.tgt.s_addr = addr.s_addr;
|
|
Packit Service |
d1fe03 |
if (ctx->flags & NFT_XT_CTX_BITWISE) {
|
|
Packit Service |
d1fe03 |
parse_mask_ipv4(ctx, &fw->arp.tmsk);
|
|
Packit Service |
d1fe03 |
ctx->flags &= ~NFT_XT_CTX_BITWISE;
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
fw->arp.tmsk.s_addr = 0xffffffff;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (inv)
|
|
Packit Service |
d1fe03 |
fw->arp.invflags |= ARPT_INV_TGTIP;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_print_header(unsigned int format, const char *chain,
|
|
Packit Service |
d1fe03 |
const char *pol,
|
|
Packit Service |
d1fe03 |
const struct xt_counters *counters,
|
|
Packit Service |
d1fe03 |
bool basechain, uint32_t refs,
|
|
Packit Service |
d1fe03 |
uint32_t entries)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
printf("Chain %s", chain);
|
|
Packit Service |
d1fe03 |
if (basechain && pol) {
|
|
Packit Service |
d1fe03 |
printf(" (policy %s", pol);
|
|
Packit Service |
d1fe03 |
if (!(format & FMT_NOCOUNTS)) {
|
|
Packit Service |
d1fe03 |
fputc(' ', stdout);
|
|
Packit Service |
d1fe03 |
xtables_print_num(counters->pcnt, (format|FMT_NOTABLE));
|
|
Packit Service |
d1fe03 |
fputs("packets, ", stdout);
|
|
Packit Service |
d1fe03 |
xtables_print_num(counters->bcnt, (format|FMT_NOTABLE));
|
|
Packit Service |
d1fe03 |
fputs("bytes", stdout);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
printf(")\n");
|
|
Packit Service |
d1fe03 |
} else {
|
|
Packit Service |
d1fe03 |
printf(" (%u references)\n", refs);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_print_rule_details(const struct iptables_command_state *cs,
|
|
Packit Service |
d1fe03 |
unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const struct arpt_entry *fw = &cs->arp;
|
|
Packit Service |
d1fe03 |
char buf[BUFSIZ];
|
|
Packit Service |
d1fe03 |
char iface[IFNAMSIZ+2];
|
|
Packit Service |
d1fe03 |
const char *sep = "";
|
|
Packit Service |
d1fe03 |
int print_iface = 0;
|
|
Packit Service |
d1fe03 |
int i;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (strlen(cs->jumpto)) {
|
|
Packit Service |
d1fe03 |
printf("%s-j %s", sep, cs->jumpto);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
iface[0] = '\0';
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.iniface[0] != '\0') {
|
|
Packit Service |
d1fe03 |
strcat(iface, fw->arp.iniface);
|
|
Packit Service |
d1fe03 |
print_iface = 1;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
else if (format & FMT_VIA) {
|
|
Packit Service |
d1fe03 |
print_iface = 1;
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC) strcat(iface, "*");
|
|
Packit Service |
d1fe03 |
else strcat(iface, "any");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
if (print_iface) {
|
|
Packit Service |
d1fe03 |
printf("%s%s-i %s", sep, fw->arp.invflags & ARPT_INV_VIA_IN ?
|
|
Packit Service |
d1fe03 |
"! " : "", iface);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
print_iface = 0;
|
|
Packit Service |
d1fe03 |
iface[0] = '\0';
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.outiface[0] != '\0') {
|
|
Packit Service |
d1fe03 |
strcat(iface, fw->arp.outiface);
|
|
Packit Service |
d1fe03 |
print_iface = 1;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
else if (format & FMT_VIA) {
|
|
Packit Service |
d1fe03 |
print_iface = 1;
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC) strcat(iface, "*");
|
|
Packit Service |
d1fe03 |
else strcat(iface, "any");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
if (print_iface) {
|
|
Packit Service |
d1fe03 |
printf("%s%s-o %s", sep, fw->arp.invflags & ARPT_INV_VIA_OUT ?
|
|
Packit Service |
d1fe03 |
"! " : "", iface);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.smsk.s_addr != 0L) {
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCIP
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC)
|
|
Packit Service |
d1fe03 |
sprintf(buf, "%s", addr_to_dotted(&(fw->arp.src)));
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
sprintf(buf, "%s", addr_to_anyname(&(fw->arp.src)));
|
|
Packit Service |
d1fe03 |
strncat(buf, mask_to_dotted(&(fw->arp.smsk)),
|
|
Packit Service |
d1fe03 |
sizeof(buf) - strlen(buf) - 1);
|
|
Packit Service |
d1fe03 |
printf("-s %s", buf);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; i < ARPT_DEV_ADDR_LEN_MAX; i++)
|
|
Packit Service |
d1fe03 |
if (fw->arp.src_devaddr.mask[i] != 0)
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
if (i == ARPT_DEV_ADDR_LEN_MAX)
|
|
Packit Service |
d1fe03 |
goto after_devsrc;
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCDEVADDR
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
printf("--src-mac ");
|
|
Packit Service |
d1fe03 |
xtables_print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr,
|
|
Packit Service |
d1fe03 |
(unsigned char *)fw->arp.src_devaddr.mask);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
after_devsrc:
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.tmsk.s_addr != 0L) {
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTIP
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
if (format & FMT_NUMERIC)
|
|
Packit Service |
d1fe03 |
sprintf(buf, "%s", addr_to_dotted(&(fw->arp.tgt)));
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
sprintf(buf, "%s", addr_to_anyname(&(fw->arp.tgt)));
|
|
Packit Service |
d1fe03 |
strncat(buf, mask_to_dotted(&(fw->arp.tmsk)),
|
|
Packit Service |
d1fe03 |
sizeof(buf) - strlen(buf) - 1);
|
|
Packit Service |
d1fe03 |
printf("-d %s", buf);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
for (i = 0; i
|
|
Packit Service |
d1fe03 |
if (fw->arp.tgt_devaddr.mask[i] != 0)
|
|
Packit Service |
d1fe03 |
break;
|
|
Packit Service |
d1fe03 |
if (i == ARPT_DEV_ADDR_LEN_MAX)
|
|
Packit Service |
d1fe03 |
goto after_devdst;
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTDEVADDR
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
printf("--dst-mac ");
|
|
Packit Service |
d1fe03 |
xtables_print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr,
|
|
Packit Service |
d1fe03 |
(unsigned char *)fw->arp.tgt_devaddr.mask);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
after_devdst:
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhln_mask != 255 || fw->arp.arhln != 6) {
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
printf("--h-length %d", fw->arp.arhln);
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhln_mask != 255)
|
|
Packit Service |
d1fe03 |
printf("/%d", fw->arp.arhln_mask);
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpop_mask != 0) {
|
|
Packit Service |
d1fe03 |
int tmp = ntohs(fw->arp.arpop);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPOP
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
if (tmp <= NUMOPCODES && !(format & FMT_NUMERIC))
|
|
Packit Service |
d1fe03 |
printf("--opcode %s", arp_opcodes[tmp-1]);
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
printf("--opcode %d", tmp);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpop_mask != 65535)
|
|
Packit Service |
d1fe03 |
printf("/%d", ntohs(fw->arp.arpop_mask));
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhrd_mask != 65535 || fw->arp.arhrd != htons(1)) {
|
|
Packit Service |
d1fe03 |
uint16_t tmp = ntohs(fw->arp.arhrd);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
if (tmp == 1 && !(format & FMT_NUMERIC))
|
|
Packit Service |
d1fe03 |
printf("--h-type %s", "Ethernet");
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
printf("--h-type %u", tmp);
|
|
Packit Service |
d1fe03 |
if (fw->arp.arhrd_mask != 65535)
|
|
Packit Service |
d1fe03 |
printf("/%d", ntohs(fw->arp.arhrd_mask));
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpro_mask != 0) {
|
|
Packit Service |
d1fe03 |
int tmp = ntohs(fw->arp.arpro);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPPRO
|
|
Packit Service |
d1fe03 |
? "! " : "");
|
|
Packit Service |
d1fe03 |
if (tmp == 0x0800 && !(format & FMT_NUMERIC))
|
|
Packit Service |
d1fe03 |
printf("--proto-type %s", "IPv4");
|
|
Packit Service |
d1fe03 |
else
|
|
Packit Service |
d1fe03 |
printf("--proto-type 0x%x", tmp);
|
|
Packit Service |
d1fe03 |
if (fw->arp.arpro_mask != 65535)
|
|
Packit Service |
d1fe03 |
printf("/%x", ntohs(fw->arp.arpro_mask));
|
|
Packit Service |
d1fe03 |
sep = " ";
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void
|
|
Packit Service |
d1fe03 |
nft_arp_save_rule(const void *data, unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
format |= FMT_NUMERIC;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
nft_arp_print_rule_details(cs, format);
|
|
Packit Service |
d1fe03 |
if (cs->target && cs->target->save)
|
|
Packit Service |
d1fe03 |
cs->target->save(&cs->fw, cs->target->t);
|
|
Packit Service |
d1fe03 |
printf("\n");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void
|
|
Packit Service |
d1fe03 |
nft_arp_print_rule(struct nft_handle *h, struct nftnl_rule *r,
|
|
Packit Service |
d1fe03 |
unsigned int num, unsigned int format)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
struct iptables_command_state cs = {};
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (format & FMT_LINENUMBERS)
|
|
Packit Service |
d1fe03 |
printf("%u ", num);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
nft_rule_to_iptables_command_state(h, r, &cs);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
nft_arp_print_rule_details(&cs, format);
|
|
Packit Service |
d1fe03 |
print_matches_and_target(&cs, format);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!(format & FMT_NOCOUNTS)) {
|
|
Packit Service |
d1fe03 |
printf(" , pcnt=");
|
|
Packit Service |
d1fe03 |
xtables_print_num(cs.counters.pcnt, format | FMT_NOTABLE);
|
|
Packit Service |
d1fe03 |
printf("-- bcnt=");
|
|
Packit Service |
d1fe03 |
xtables_print_num(cs.counters.bcnt, format | FMT_NOTABLE);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!(format & FMT_NONEWLINE))
|
|
Packit Service |
d1fe03 |
fputc('\n', stdout);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static bool nft_arp_is_same(const void *data_a,
|
|
Packit Service |
d1fe03 |
const void *data_b)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const struct arpt_entry *a = data_a;
|
|
Packit Service |
d1fe03 |
const struct arpt_entry *b = data_b;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (a->arp.src.s_addr != b->arp.src.s_addr
|
|
Packit Service |
d1fe03 |
|| a->arp.tgt.s_addr != b->arp.tgt.s_addr
|
|
Packit Service |
d1fe03 |
|| a->arp.smsk.s_addr != b->arp.smsk.s_addr
|
|
Packit Service |
d1fe03 |
|| a->arp.tmsk.s_addr != b->arp.tmsk.s_addr
|
|
Packit Service |
d1fe03 |
|| a->arp.arpro != b->arp.arpro
|
|
Packit Service |
d1fe03 |
|| a->arp.flags != b->arp.flags
|
|
Packit Service |
d1fe03 |
|| a->arp.invflags != b->arp.invflags) {
|
|
Packit Service |
d1fe03 |
DEBUGP("different src/dst/proto/flags/invflags\n");
|
|
Packit Service |
d1fe03 |
return false;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
return is_same_interfaces(a->arp.iniface,
|
|
Packit Service |
d1fe03 |
a->arp.outiface,
|
|
Packit Service |
d1fe03 |
(unsigned char *)a->arp.iniface_mask,
|
|
Packit Service |
d1fe03 |
(unsigned char *)a->arp.outiface_mask,
|
|
Packit Service |
d1fe03 |
b->arp.iniface,
|
|
Packit Service |
d1fe03 |
b->arp.outiface,
|
|
Packit Service |
d1fe03 |
(unsigned char *)b->arp.iniface_mask,
|
|
Packit Service |
d1fe03 |
(unsigned char *)b->arp.outiface_mask);
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static bool nft_arp_rule_find(struct nft_handle *h, struct nftnl_rule *r,
|
|
Packit Service |
d1fe03 |
void *data)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const struct iptables_command_state *cs = data;
|
|
Packit Service |
d1fe03 |
struct iptables_command_state this = {};
|
|
Packit Service |
d1fe03 |
bool ret = false;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
/* Delete by matching rule case */
|
|
Packit Service |
d1fe03 |
nft_rule_to_iptables_command_state(h, r, &this;;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!nft_arp_is_same(&cs->arp, &this.arp))
|
|
Packit Service |
d1fe03 |
goto out;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (!compare_targets(cs->target, this.target))
|
|
Packit Service |
d1fe03 |
goto out;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
if (this.jumpto && strcmp(cs->jumpto, this.jumpto) != 0)
|
|
Packit Service |
d1fe03 |
goto out;
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
ret = true;
|
|
Packit Service |
d1fe03 |
out:
|
|
Packit Service |
d1fe03 |
h->ops->clear_cs(&this;;
|
|
Packit Service |
d1fe03 |
return ret;
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy)
|
|
Packit Service |
d1fe03 |
{
|
|
Packit Service |
d1fe03 |
const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
printf(":%s %s\n", chain, policy ?: "-");
|
|
Packit Service |
d1fe03 |
}
|
|
Packit Service |
d1fe03 |
|
|
Packit Service |
d1fe03 |
struct nft_family_ops nft_family_ops_arp = {
|
|
Packit Service |
d1fe03 |
.add = nft_arp_add,
|
|
Packit Service |
d1fe03 |
.is_same = nft_arp_is_same,
|
|
Packit Service |
d1fe03 |
.print_payload = NULL,
|
|
Packit Service |
d1fe03 |
.parse_meta = nft_arp_parse_meta,
|
|
Packit Service |
d1fe03 |
.parse_payload = nft_arp_parse_payload,
|
|
Packit Service |
d1fe03 |
.parse_immediate = nft_arp_parse_immediate,
|
|
Packit Service |
d1fe03 |
.print_header = nft_arp_print_header,
|
|
Packit Service |
d1fe03 |
.print_rule = nft_arp_print_rule,
|
|
Packit Service |
d1fe03 |
.save_rule = nft_arp_save_rule,
|
|
Packit Service |
d1fe03 |
.save_counters = save_counters,
|
|
Packit Service |
d1fe03 |
.save_chain = nft_arp_save_chain,
|
|
Packit Service |
d1fe03 |
.post_parse = NULL,
|
|
Packit Service |
d1fe03 |
.rule_to_cs = nft_rule_to_iptables_command_state,
|
|
Packit Service |
d1fe03 |
.clear_cs = nft_clear_iptables_command_state,
|
|
Packit Service |
d1fe03 |
.rule_find = nft_arp_rule_find,
|
|
Packit Service |
d1fe03 |
.parse_target = nft_ipv46_parse_target,
|
|
Packit Service |
d1fe03 |
};
|