diff options
Diffstat (limited to 'iptables/xtables-arp.c')
-rw-r--r-- | iptables/xtables-arp.c | 1326 |
1 files changed, 5 insertions, 1321 deletions
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c index 35844a9b..71518a9c 100644 --- a/iptables/xtables-arp.c +++ b/iptables/xtables-arp.c @@ -30,89 +30,22 @@ #include "config.h" #include <getopt.h> #include <string.h> -#include <netdb.h> -#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <inttypes.h> -#include <dlfcn.h> -#include <ctype.h> -#include <stdarg.h> -#include <limits.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/wait.h> -#include <net/if.h> -#include <netinet/ether.h> -#include <iptables.h> #include <xtables.h> #include "xshared.h" #include "nft.h" -#include "nft-arp.h" -#include <linux/netfilter_arp/arp_tables.h> - -typedef char arpt_chainlabel[32]; - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -/* XXX: command defined by nft-shared.h do not overlap with these two */ -#undef CMD_CHECK -#undef CMD_RENAME_CHAIN - -#define CMD_NONE 0x0000U -#define CMD_INSERT 0x0001U -#define CMD_DELETE 0x0002U -#define CMD_DELETE_NUM 0x0004U -#define CMD_REPLACE 0x0008U -#define CMD_APPEND 0x0010U -#define CMD_LIST 0x0020U -#define CMD_FLUSH 0x0040U -#define CMD_ZERO 0x0080U -#define CMD_NEW_CHAIN 0x0100U -#define CMD_DELETE_CHAIN 0x0200U -#define CMD_SET_POLICY 0x0400U -#define CMD_CHECK 0x0800U -#define CMD_RENAME_CHAIN 0x1000U -#define NUMBER_OF_CMD 13 -static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z', - 'N', 'X', 'P', 'E' }; - -#define OPTION_OFFSET 256 - -#define OPT_NONE 0x00000U -#define OPT_NUMERIC 0x00001U -#define OPT_S_IP 0x00002U -#define OPT_D_IP 0x00004U -#define OPT_S_MAC 0x00008U -#define OPT_D_MAC 0x00010U -#define OPT_H_LENGTH 0x00020U -#define OPT_P_LENGTH 0x00040U -#define OPT_OPCODE 0x00080U -#define OPT_H_TYPE 0x00100U -#define OPT_P_TYPE 0x00200U -#define OPT_JUMP 0x00400U -#define OPT_VERBOSE 0x00800U -#define OPT_VIANAMEIN 0x01000U -#define OPT_VIANAMEOUT 0x02000U -#define OPT_LINENUMBERS 0x04000U -#define OPT_COUNTERS 0x08000U -#define NUMBER_OF_OPT 16 -static const char optflags[NUMBER_OF_OPT] -= { 'n', 's', 'd', 2, 3, 7, 8, 4, 5, 6, 'j', 'v', 'i', 'o', '0', 'c'}; static struct option original_opts[] = { { "append", 1, 0, 'A' }, { "delete", 1, 0, 'D' }, + { "check", 1, 0, 'C'}, { "insert", 1, 0, 'I' }, { "replace", 1, 0, 'R' }, { "list", 2, 0, 'L' }, + { "list-rules", 2, 0, 'S'}, { "flush", 2, 0, 'F' }, { "zero", 2, 0, 'Z' }, { "new-chain", 1, 0, 'N' }, @@ -148,735 +81,15 @@ static struct option original_opts[] = { { 0 } }; -int RUNTIME_NF_ARP_NUMHOOKS = 3; - #define opts xt_params->opts -extern void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); struct xtables_globals arptables_globals = { .option_offset = 0, - .program_version = PACKAGE_VERSION, + .program_version = PACKAGE_VERSION " (nf_tables)", .orig_opts = original_opts, - .exit_err = xtables_exit_error, .compat_rev = nft_compatible_revision, }; -/* Table of legal combinations of commands and options. If any of the - * given commands make an option legal, that option is legal (applies to - * CMD_LIST and CMD_ZERO only). - * Key: - * + compulsory - * x illegal - * optional - */ - -static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = -/* Well, it's better than "Re: Linux vs FreeBSD" */ -{ - /* -n -s -d -p -j -v -x -i -o -f --line */ -/*INSERT*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*DELETE*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*DELETE_NUM*/{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*REPLACE*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*APPEND*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*LIST*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*FLUSH*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*ZERO*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*NEW_CHAIN*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*DEL_CHAIN*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*SET_POLICY*/{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*CHECK*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, -/*RENAME*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '} -}; - -static int inverse_for_options[NUMBER_OF_OPT] = -{ -/* -n */ 0, -/* -s */ ARPT_INV_SRCIP, -/* -d */ ARPT_INV_TGTIP, -/* 2 */ ARPT_INV_SRCDEVADDR, -/* 3 */ ARPT_INV_TGTDEVADDR, -/* -l */ ARPT_INV_ARPHLN, -/* 8 */ 0, -/* 4 */ ARPT_INV_ARPOP, -/* 5 */ ARPT_INV_ARPHRD, -/* 6 */ ARPT_INV_ARPPRO, -/* -j */ 0, -/* -v */ 0, -/* -i */ ARPT_INV_VIA_IN, -/* -o */ ARPT_INV_VIA_OUT, -/*--line*/ 0, -/* -c */ 0, -}; - -/* A few hardcoded protocols for 'all' and in case the user has no - /etc/protocols */ -struct pprot { - char *name; - u_int8_t num; -}; - -/* Primitive headers... */ -/* defined in netinet/in.h */ -#if 0 -#ifndef IPPROTO_ESP -#define IPPROTO_ESP 50 -#endif -#ifndef IPPROTO_AH -#define IPPROTO_AH 51 -#endif -#endif - -/***********************************************/ -/* ARPTABLES SPECIFIC NEW FUNCTIONS ADDED HERE */ -/***********************************************/ - -static unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0}; -static unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0}; -static unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0}; -static unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0}; -static unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; -static unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; - -/* - * put the mac address into 6 (ETH_ALEN) bytes - */ -static int getmac_and_mask(char *from, char *to, char *mask) -{ - char *p; - int i; - struct ether_addr *addr; - - if (strcasecmp(from, "Unicast") == 0) { - memcpy(to, mac_type_unicast, ETH_ALEN); - memcpy(mask, msk_type_unicast, ETH_ALEN); - return 0; - } - if (strcasecmp(from, "Multicast") == 0) { - memcpy(to, mac_type_multicast, ETH_ALEN); - memcpy(mask, msk_type_multicast, ETH_ALEN); - return 0; - } - if (strcasecmp(from, "Broadcast") == 0) { - memcpy(to, mac_type_broadcast, ETH_ALEN); - memcpy(mask, msk_type_broadcast, ETH_ALEN); - return 0; - } - if ( (p = strrchr(from, '/')) != NULL) { - *p = '\0'; - if (!(addr = ether_aton(p + 1))) - return -1; - memcpy(mask, addr, ETH_ALEN); - } else - memset(mask, 0xff, ETH_ALEN); - if (!(addr = ether_aton(from))) - return -1; - memcpy(to, addr, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) - to[i] &= mask[i]; - return 0; -} - -static int getlength_and_mask(char *from, uint8_t *to, uint8_t *mask) -{ - char *p, *buffer; - int i; - - if ( (p = strrchr(from, '/')) != NULL) { - *p = '\0'; - i = strtol(p+1, &buffer, 10); - if (*buffer != '\0' || i < 0 || i > 255) - return -1; - *mask = (uint8_t)i; - } else - *mask = 255; - i = strtol(from, &buffer, 10); - if (*buffer != '\0' || i < 0 || i > 255) - return -1; - *to = (uint8_t)i; - return 0; -} - -static int get16_and_mask(char *from, uint16_t *to, uint16_t *mask, int base) -{ - char *p, *buffer; - int i; - - if ( (p = strrchr(from, '/')) != NULL) { - *p = '\0'; - i = strtol(p+1, &buffer, base); - if (*buffer != '\0' || i < 0 || i > 65535) - return -1; - *mask = htons((uint16_t)i); - } else - *mask = 65535; - i = strtol(from, &buffer, base); - if (*buffer != '\0' || i < 0 || i > 65535) - return -1; - *to = htons((uint16_t)i); - return 0; -} - -static int -string_to_number(const char *s, unsigned int min, unsigned int max, - unsigned int *ret) -{ - long number; - char *end; - - /* Handle hex, octal, etc. */ - errno = 0; - number = strtol(s, &end, 0); - if (*end == '\0' && end != s) { - /* we parsed a number, let's see if we want this */ - if (errno != ERANGE && min <= number && number <= max) { - *ret = number; - return 0; - } - } - return -1; -} - -/*********************************************/ -/* ARPTABLES SPECIFIC NEW FUNCTIONS END HERE */ -/*********************************************/ - -static struct in_addr * -dotted_to_addr(const char *dotted) -{ - static struct in_addr addr; - unsigned char *addrp; - char *p, *q; - unsigned int onebyte; - int i; - char buf[20]; - - /* copy dotted string, because we need to modify it */ - strncpy(buf, dotted, sizeof(buf) - 1); - addrp = (unsigned char *) &(addr.s_addr); - - p = buf; - for (i = 0; i < 3; i++) { - if ((q = strchr(p, '.')) == NULL) - return (struct in_addr *) NULL; - - *q = '\0'; - if (string_to_number(p, 0, 255, &onebyte) == -1) - return (struct in_addr *) NULL; - - addrp[i] = (unsigned char) onebyte; - p = q + 1; - } - - /* we've checked 3 bytes, now we check the last one */ - if (string_to_number(p, 0, 255, &onebyte) == -1) - return (struct in_addr *) NULL; - - addrp[3] = (unsigned char) onebyte; - - return &addr; -} - -static struct in_addr * -network_to_addr(const char *name) -{ - struct netent *net; - static struct in_addr addr; - - if ((net = getnetbyname(name)) != NULL) { - if (net->n_addrtype != AF_INET) - return (struct in_addr *) NULL; - addr.s_addr = htonl((unsigned long) net->n_net); - return &addr; - } - - return (struct in_addr *) NULL; -} - -static void -inaddrcpy(struct in_addr *dst, struct in_addr *src) -{ - /* memcpy(dst, src, sizeof(struct in_addr)); */ - dst->s_addr = src->s_addr; -} - -static void -exit_tryhelp(int status) -{ - fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", - arptables_globals.program_name, - arptables_globals.program_version); - exit(status); -} - -static void -exit_printhelp(void) -{ - struct xtables_target *t = NULL; - int i; - - printf("%s v%s\n\n" -"Usage: %s -[AD] chain rule-specification [options]\n" -" %s -[RI] chain rulenum rule-specification [options]\n" -" %s -D chain rulenum [options]\n" -" %s -[LFZ] [chain] [options]\n" -" %s -[NX] chain\n" -" %s -E old-chain-name new-chain-name\n" -" %s -P chain target [options]\n" -" %s -h (print this help information)\n\n", - arptables_globals.program_name, - arptables_globals.program_version, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name, - arptables_globals.program_name); - printf( -"Commands:\n" -"Either long or short options are allowed.\n" -" --append -A chain Append to chain\n" -" --delete -D chain Delete matching rule from chain\n" -" --delete -D chain rulenum\n" -" Delete rule rulenum (1 = first) from chain\n" -" --insert -I chain [rulenum]\n" -" Insert in chain as rulenum (default 1=first)\n" -" --replace -R chain rulenum\n" -" Replace rule rulenum (1 = first) in chain\n" -" --list -L [chain] List the rules in a chain or all chains\n" -" --flush -F [chain] Delete all rules in chain or all chains\n" -" --zero -Z [chain] Zero counters in chain or all chains\n" -" --new -N chain Create a new user-defined chain\n" -" --delete-chain\n" -" -X [chain] Delete a user-defined chain\n" -" --policy -P chain target\n" -" Change policy on chain to target\n" -" --rename-chain\n" -" -E old-chain new-chain\n" -" Change chain name, (moving any references)\n" - -"Options:\n" -" --source-ip -s [!] address[/mask]\n" -" source specification\n" -" --destination-ip -d [!] address[/mask]\n" -" destination specification\n" -" --source-mac [!] address[/mask]\n" -" --destination-mac [!] address[/mask]\n" -" --h-length -l length[/mask] hardware length (nr of bytes)\n" -" --opcode code[/mask] operation code (2 bytes)\n" -" --h-type type[/mask] hardware type (2 bytes, hexadecimal)\n" -" --proto-type type[/mask] protocol type (2 bytes)\n" -" --in-interface -i [!] input name[+]\n" -" network interface name ([+] for wildcard)\n" -" --out-interface -o [!] output name[+]\n" -" network interface name ([+] for wildcard)\n" -" --jump -j target\n" -" target for rule (may load target extension)\n" -" --match -m match\n" -" extended match (may load extension)\n" -" --numeric -n numeric output of addresses and ports\n" -" --table -t table table to manipulate (default: `filter')\n" -" --verbose -v verbose mode\n" -" --line-numbers print line numbers when listing\n" -" --exact -x expand numbers (display exact values)\n" -" --modprobe=<command> try to insert modules using this command\n" -" --set-counters -c PKTS BYTES set the counter during insert/append\n" -"[!] --version -V print package version.\n"); - printf(" opcode strings: \n"); - for (i = 0; i < NUMOPCODES; i++) - printf(" %d = %s\n", i + 1, arp_opcodes[i]); - printf( -" hardware type string: 1 = Ethernet\n" -" protocol type string: 0x800 = IPv4\n"); - - /* Print out any special helps. A user might like to be able - to add a --help to the commandline, and see expected - results. So we call help for all matches & targets */ - for (t = xtables_targets; t; t = t->next) { - if (strcmp(t->name, "CLASSIFY") && strcmp(t->name, "mangle")) - continue; - printf("\n"); - t->help(); - } - exit(0); -} - -static void -generic_opt_check(int command, int options) -{ - int i, j, legal = 0; - - /* Check that commands are valid with options. Complicated by the - * fact that if an option is legal with *any* command given, it is - * legal overall (ie. -z and -l). - */ - for (i = 0; i < NUMBER_OF_OPT; i++) { - legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */ - - for (j = 0; j < NUMBER_OF_CMD; j++) { - if (!(command & (1<<j))) - continue; - - if (!(options & (1<<i))) { - if (commands_v_options[j][i] == '+') - xtables_error(PARAMETER_PROBLEM, - "You need to supply the `-%c' " - "option for this command\n", - optflags[i]); - } else { - if (commands_v_options[j][i] != 'x') - legal = 1; - else if (legal == 0) - legal = -1; - } - } - if (legal == -1) - xtables_error(PARAMETER_PROBLEM, - "Illegal option `-%c' with this command\n", - optflags[i]); - } -} - -static char -opt2char(int option) -{ - const char *ptr; - for (ptr = optflags; option > 1; option >>= 1, ptr++); - - return *ptr; -} - -static char -cmd2char(int option) -{ - const char *ptr; - for (ptr = cmdflags; option > 1; option >>= 1, ptr++); - - return *ptr; -} - -static void -add_command(unsigned int *cmd, const int newcmd, const unsigned int othercmds, int invert) -{ - if (invert) - xtables_error(PARAMETER_PROBLEM, "unexpected ! flag"); - if (*cmd & (~othercmds)) - xtables_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n", - cmd2char(newcmd), cmd2char(*cmd & (~othercmds))); - *cmd |= newcmd; -} - -static int -check_inverse(const char option[], int *invert, int *optidx, int argc) -{ - if (option && strcmp(option, "!") == 0) { - if (*invert) - xtables_error(PARAMETER_PROBLEM, - "Multiple `!' flags not allowed"); - *invert = TRUE; - if (optidx) { - *optidx = *optidx+1; - if (argc && *optidx > argc) - xtables_error(PARAMETER_PROBLEM, - "no argument following `!'"); - } - - return TRUE; - } - return FALSE; -} - -static struct in_addr * -host_to_addr(const char *name, unsigned int *naddr) -{ - struct in_addr *addr; - struct addrinfo hints = { - .ai_flags = AI_CANONNAME, - .ai_family = AF_INET, - .ai_socktype = SOCK_RAW, - };; - struct addrinfo *res, *p; - int err; - unsigned int i; - - *naddr = 0; - err = getaddrinfo(name, NULL, &hints, &res); - if (err != 0) - return NULL; - else { - for (p = res; p != NULL; p = p->ai_next) - (*naddr)++; - addr = xtables_calloc(*naddr, sizeof(struct in_addr)); - for (i = 0, p = res; p != NULL; p = p->ai_next) - memcpy(&addr[i++], - &((const struct sockaddr_in *)p->ai_addr)->sin_addr, - sizeof(struct in_addr)); - freeaddrinfo(res); - return addr; - } - - return (struct in_addr *) NULL; -} - -/* - * All functions starting with "parse" should succeed, otherwise - * the program fails. - * Most routines return pointers to static data that may change - * between calls to the same or other routines with a few exceptions: - * "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask" - * return global static data. -*/ - -static struct in_addr * -parse_hostnetwork(const char *name, unsigned int *naddrs) -{ - struct in_addr *addrp, *addrptmp; - - if ((addrptmp = dotted_to_addr(name)) != NULL || - (addrptmp = network_to_addr(name)) != NULL) { - addrp = xtables_malloc(sizeof(struct in_addr)); - inaddrcpy(addrp, addrptmp); - *naddrs = 1; - return addrp; - } - if ((addrp = host_to_addr(name, naddrs)) != NULL) - return addrp; - - xtables_error(PARAMETER_PROBLEM, "host/network `%s' not found", name); -} - -static struct in_addr * -parse_mask(char *mask) -{ - static struct in_addr maskaddr; - struct in_addr *addrp; - unsigned int bits; - - if (mask == NULL) { - /* no mask at all defaults to 32 bits */ - maskaddr.s_addr = 0xFFFFFFFF; - return &maskaddr; - } - if ((addrp = dotted_to_addr(mask)) != NULL) - /* dotted_to_addr already returns a network byte order addr */ - return addrp; - if (string_to_number(mask, 0, 32, &bits) == -1) - xtables_error(PARAMETER_PROBLEM, - "invalid mask `%s' specified", mask); - if (bits != 0) { - maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); - return &maskaddr; - } - - maskaddr.s_addr = 0L; - return &maskaddr; -} - -static void -parse_hostnetworkmask(const char *name, struct in_addr **addrpp, - struct in_addr *maskp, unsigned int *naddrs) -{ - struct in_addr *addrp; - char buf[256]; - char *p; - int i, j, k, n; - - strncpy(buf, name, sizeof(buf) - 1); - if ((p = strrchr(buf, '/')) != NULL) { - *p = '\0'; - addrp = parse_mask(p + 1); - } else - addrp = parse_mask(NULL); - inaddrcpy(maskp, addrp); - - /* if a null mask is given, the name is ignored, like in "any/0" */ - if (maskp->s_addr == 0L) - strcpy(buf, "0.0.0.0"); - - addrp = *addrpp = parse_hostnetwork(buf, naddrs); - n = *naddrs; - for (i = 0, j = 0; i < n; i++) { - addrp[j++].s_addr &= maskp->s_addr; - for (k = 0; k < j - 1; k++) { - if (addrp[k].s_addr == addrp[j - 1].s_addr) { - (*naddrs)--; - j--; - break; - } - } - } -} - -static void -parse_interface(const char *arg, char *vianame, unsigned char *mask) -{ - int vialen = strlen(arg); - unsigned int i; - - memset(mask, 0, IFNAMSIZ); - memset(vianame, 0, IFNAMSIZ); - - if (vialen + 1 > IFNAMSIZ) - xtables_error(PARAMETER_PROBLEM, - "interface name `%s' must be shorter than IFNAMSIZ" - " (%i)", arg, IFNAMSIZ-1); - - strcpy(vianame, arg); - if (vialen == 0) - memset(mask, 0, IFNAMSIZ); - else if (vianame[vialen - 1] == '+') { - memset(mask, 0xFF, vialen - 1); - memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); - /* Don't remove `+' here! -HW */ - } else { - /* Include nul-terminator in match */ - memset(mask, 0xFF, vialen + 1); - memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); - for (i = 0; vianame[i]; i++) { - if (!isalnum(vianame[i]) - && vianame[i] != '_' - && vianame[i] != '.') { - printf("Warning: weird character in interface" - " `%s' (No aliases, :, ! or *).\n", - vianame); - break; - } - } - } -} - -/* Can't be zero. */ -static int -parse_rulenumber(const char *rule) -{ - unsigned int rulenum; - - if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX)) - xtables_error(PARAMETER_PROBLEM, - "Invalid rule number `%s'", rule); - - return rulenum; -} - -static void -set_option(unsigned int *options, unsigned int option, u_int16_t *invflg, - int invert) -{ - if (*options & option) - xtables_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed", - opt2char(option)); - *options |= option; - - if (invert) { - unsigned int i; - for (i = 0; 1 << i != option; i++); - - if (!inverse_for_options[i]) - xtables_error(PARAMETER_PROBLEM, - "cannot have ! before -%c", - opt2char(option)); - *invflg |= inverse_for_options[i]; - } -} - -static int -list_entries(struct nft_handle *h, const char *chain, const char *table, - int rulenum, int verbose, int numeric, int expanded, - int linenumbers) -{ - unsigned int format; - - format = FMT_OPTIONS; - if (!verbose) - format |= FMT_NOCOUNTS; - else - format |= FMT_VIA; - - if (numeric) - format |= FMT_NUMERIC; - - if (!expanded) - format |= FMT_KILOMEGAGIGA; - - if (linenumbers) - format |= FMT_LINENUMBERS; - - return nft_rule_list(h, chain, table, rulenum, format); -} - -static int -append_entry(struct nft_handle *h, - const char *chain, - const char *table, - struct iptables_command_state *cs, - int rulenum, - unsigned int nsaddrs, - const struct in_addr saddrs[], - unsigned int ndaddrs, - const struct in_addr daddrs[], - bool verbose, bool append) -{ - unsigned int i, j; - int ret = 1; - - for (i = 0; i < nsaddrs; i++) { - cs->arp.arp.src.s_addr = saddrs[i].s_addr; - for (j = 0; j < ndaddrs; j++) { - cs->arp.arp.tgt.s_addr = daddrs[j].s_addr; - if (append) { - ret = nft_rule_append(h, chain, table, cs, NULL, - verbose); - } else { - ret = nft_rule_insert(h, chain, table, cs, - rulenum, verbose); - } - } - } - - return ret; -} - -static int -replace_entry(const char *chain, - const char *table, - struct iptables_command_state *cs, - unsigned int rulenum, - const struct in_addr *saddr, - const struct in_addr *daddr, - bool verbose, struct nft_handle *h) -{ - cs->arp.arp.src.s_addr = saddr->s_addr; - cs->arp.arp.tgt.s_addr = daddr->s_addr; - - return nft_rule_replace(h, chain, table, cs, rulenum, verbose); -} - -static int -delete_entry(const char *chain, - const char *table, - struct iptables_command_state *cs, - unsigned int nsaddrs, - const struct in_addr saddrs[], - unsigned int ndaddrs, - const struct in_addr daddrs[], - bool verbose, struct nft_handle *h) -{ - unsigned int i, j; - int ret = 1; - - for (i = 0; i < nsaddrs; i++) { - cs->arp.arp.src.s_addr = saddrs[i].s_addr; - for (j = 0; j < ndaddrs; j++) { - cs->arp.arp.tgt.s_addr = daddrs[j].s_addr; - ret = nft_rule_delete(h, chain, table, cs, verbose); - } - } - - return ret; -} - int nft_init_arp(struct nft_handle *h, const char *pname) { arptables_globals.program_name = pname; @@ -886,541 +99,12 @@ int nft_init_arp(struct nft_handle *h, const char *pname) arptables_globals.program_version); exit(1); } - -#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) + init_extensions(); init_extensionsa(); -#endif - - memset(h, 0, sizeof(*h)); - h->family = NFPROTO_ARP; - if (nft_init(h, xtables_arp) < 0) + if (nft_init(h, NFPROTO_ARP) < 0) xtables_error(OTHER_PROBLEM, "Could not initialize nftables layer."); - h->ops = nft_family_ops_lookup(h->family); - if (h->ops == NULL) - xtables_error(PARAMETER_PROBLEM, "Unknown family"); - return 0; } - -int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, - bool restore) -{ - struct iptables_command_state cs = { - .jumpto = "", - .arp.arp = { - .arhln = 6, - .arhln_mask = 255, - .arhrd = htons(ARPHRD_ETHER), - .arhrd_mask = 65535, - }, - }; - int invert = 0; - unsigned int nsaddrs = 0, ndaddrs = 0; - struct in_addr *saddrs = NULL, *daddrs = NULL; - - int c, verbose = 0; - const char *chain = NULL; - const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; - const char *policy = NULL, *newname = NULL; - unsigned int rulenum = 0, options = 0, command = 0; - const char *pcnt = NULL, *bcnt = NULL; - int ret = 1; - struct xtables_target *t; - - /* re-set optind to 0 in case do_command gets called - * a second time */ - optind = 0; - - for (t = xtables_targets; t; t = t->next) { - t->tflags = 0; - t->used = 0; - } - - /* Suppress error messages: we may add new options if we - demand-load a protocol. */ - opterr = 0; - - opts = xt_params->orig_opts; - while ((c = getopt_long(argc, argv, - "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:l:i:vnt:m:c:", - opts, NULL)) != -1) { - switch (c) { - /* - * Command selection - */ - case 'A': - add_command(&command, CMD_APPEND, CMD_NONE, - invert); - chain = optarg; - break; - - case 'D': - add_command(&command, CMD_DELETE, CMD_NONE, - invert); - chain = optarg; - if (xs_has_arg(argc, argv)) { - rulenum = parse_rulenumber(argv[optind++]); - command = CMD_DELETE_NUM; - } - break; - - case 'R': - add_command(&command, CMD_REPLACE, CMD_NONE, - invert); - chain = optarg; - if (xs_has_arg(argc, argv)) - rulenum = parse_rulenumber(argv[optind++]); - else - xtables_error(PARAMETER_PROBLEM, - "-%c requires a rule number", - cmd2char(CMD_REPLACE)); - break; - - case 'I': - add_command(&command, CMD_INSERT, CMD_NONE, - invert); - chain = optarg; - if (xs_has_arg(argc, argv)) - rulenum = parse_rulenumber(argv[optind++]); - else rulenum = 1; - break; - - case 'L': - add_command(&command, CMD_LIST, CMD_ZERO, - invert); - if (optarg) chain = optarg; - else if (xs_has_arg(argc, argv)) - chain = argv[optind++]; - break; - - case 'F': - add_command(&command, CMD_FLUSH, CMD_NONE, - invert); - if (optarg) chain = optarg; - else if (xs_has_arg(argc, argv)) - chain = argv[optind++]; - break; - - case 'Z': - add_command(&command, CMD_ZERO, CMD_LIST, - invert); - if (optarg) chain = optarg; - else if (xs_has_arg(argc, argv)) - chain = argv[optind++]; - break; - - case 'N': - if (optarg && *optarg == '-') - xtables_error(PARAMETER_PROBLEM, - "chain name not allowed to start " - "with `-'\n"); - if (xtables_find_target(optarg, XTF_TRY_LOAD)) - xtables_error(PARAMETER_PROBLEM, - "chain name may not clash " - "with target name\n"); - add_command(&command, CMD_NEW_CHAIN, CMD_NONE, - invert); - chain = optarg; - break; - - case 'X': - add_command(&command, CMD_DELETE_CHAIN, CMD_NONE, - invert); - if (optarg) chain = optarg; - else if (xs_has_arg(argc, argv)) - chain = argv[optind++]; - break; - - case 'E': - add_command(&command, CMD_RENAME_CHAIN, CMD_NONE, - invert); - chain = optarg; - if (xs_has_arg(argc, argv)) - newname = argv[optind++]; - else - xtables_error(PARAMETER_PROBLEM, - "-%c requires old-chain-name and " - "new-chain-name", - cmd2char(CMD_RENAME_CHAIN)); - break; - - case 'P': - add_command(&command, CMD_SET_POLICY, CMD_NONE, - invert); - chain = optarg; - if (xs_has_arg(argc, argv)) - policy = argv[optind++]; - else - xtables_error(PARAMETER_PROBLEM, - "-%c requires a chain and a policy", - cmd2char(CMD_SET_POLICY)); - break; - - case 'h': - if (!optarg) - optarg = argv[optind]; - - exit_printhelp(); - break; - case 's': - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_S_IP, &cs.arp.arp.invflags, - invert); - shostnetworkmask = argv[optind-1]; - break; - - case 'd': - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_D_IP, &cs.arp.arp.invflags, - invert); - dhostnetworkmask = argv[optind-1]; - break; - - case 2:/* src-mac */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_S_MAC, &cs.arp.arp.invflags, - invert); - if (getmac_and_mask(argv[optind - 1], - cs.arp.arp.src_devaddr.addr, cs.arp.arp.src_devaddr.mask)) - xtables_error(PARAMETER_PROBLEM, "Problem with specified " - "source mac"); - break; - - case 3:/* dst-mac */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_D_MAC, &cs.arp.arp.invflags, - invert); - - if (getmac_and_mask(argv[optind - 1], - cs.arp.arp.tgt_devaddr.addr, cs.arp.arp.tgt_devaddr.mask)) - xtables_error(PARAMETER_PROBLEM, "Problem with specified " - "destination mac"); - break; - - case 'l':/* hardware length */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_H_LENGTH, &cs.arp.arp.invflags, - invert); - getlength_and_mask(argv[optind - 1], &cs.arp.arp.arhln, - &cs.arp.arp.arhln_mask); - - if (cs.arp.arp.arhln != 6) { - xtables_error(PARAMETER_PROBLEM, - "Only harware address length of" - " 6 is supported currently."); - } - - break; - - case 8: /* was never supported, not even in arptables-legacy */ - xtables_error(PARAMETER_PROBLEM, "not supported"); - case 4:/* opcode */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_OPCODE, &cs.arp.arp.invflags, - invert); - if (get16_and_mask(argv[optind - 1], &cs.arp.arp.arpop, - &cs.arp.arp.arpop_mask, 10)) { - int i; - - for (i = 0; i < NUMOPCODES; i++) - if (!strcasecmp(arp_opcodes[i], optarg)) - break; - if (i == NUMOPCODES) - xtables_error(PARAMETER_PROBLEM, "Problem with specified opcode"); - cs.arp.arp.arpop = htons(i+1); - } - break; - - case 5:/* h-type */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_H_TYPE, &cs.arp.arp.invflags, - invert); - if (get16_and_mask(argv[optind - 1], &cs.arp.arp.arhrd, - &cs.arp.arp.arhrd_mask, 16)) { - if (strcasecmp(argv[optind-1], "Ethernet")) - xtables_error(PARAMETER_PROBLEM, "Problem with specified hardware type"); - cs.arp.arp.arhrd = htons(1); - } - break; - - case 6:/* proto-type */ - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_P_TYPE, &cs.arp.arp.invflags, - invert); - if (get16_and_mask(argv[optind - 1], &cs.arp.arp.arpro, - &cs.arp.arp.arpro_mask, 0)) { - if (strcasecmp(argv[optind-1], "ipv4")) - xtables_error(PARAMETER_PROBLEM, "Problem with specified protocol type"); - cs.arp.arp.arpro = htons(0x800); - } - break; - - case 'j': - set_option(&options, OPT_JUMP, &cs.arp.arp.invflags, - invert); - command_jump(&cs, optarg); - break; - - case 'i': - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_VIANAMEIN, &cs.arp.arp.invflags, - invert); - parse_interface(argv[optind-1], - cs.arp.arp.iniface, - cs.arp.arp.iniface_mask); - break; - - case 'o': - check_inverse(optarg, &invert, &optind, argc); - set_option(&options, OPT_VIANAMEOUT, &cs.arp.arp.invflags, - invert); - parse_interface(argv[optind-1], - cs.arp.arp.outiface, - cs.arp.arp.outiface_mask); - break; - - case 'v': - if (!verbose) - set_option(&options, OPT_VERBOSE, - &cs.arp.arp.invflags, invert); - verbose++; - break; - - case 'm': /* ignored by arptables-legacy */ - break; - case 'n': - set_option(&options, OPT_NUMERIC, &cs.arp.arp.invflags, - invert); - break; - - case 't': - if (invert) - xtables_error(PARAMETER_PROBLEM, - "unexpected ! flag before --table"); - /* ignore this option. - * arptables-legacy parses it, but libarptc doesn't use it. - * arptables only has a 'filter' table anyway. - */ - break; - - case 'V': - if (invert) - printf("Not %s ;-)\n", arptables_globals.program_version); - else - printf("%s v%s (nf_tables)\n", - arptables_globals.program_name, - arptables_globals.program_version); - exit(0); - - case '0': - set_option(&options, OPT_LINENUMBERS, &cs.arp.arp.invflags, - invert); - break; - - case 'M': - //modprobe = optarg; - break; - - case 'c': - - set_option(&options, OPT_COUNTERS, &cs.arp.arp.invflags, - invert); - pcnt = optarg; - if (xs_has_arg(argc, argv)) - bcnt = argv[optind++]; - else - xtables_error(PARAMETER_PROBLEM, - "-%c requires packet and byte counter", - opt2char(OPT_COUNTERS)); - - if (sscanf(pcnt, "%llu", &cs.arp.counters.pcnt) != 1) - xtables_error(PARAMETER_PROBLEM, - "-%c packet counter not numeric", - opt2char(OPT_COUNTERS)); - - if (sscanf(bcnt, "%llu", &cs.arp.counters.bcnt) != 1) - xtables_error(PARAMETER_PROBLEM, - "-%c byte counter not numeric", - opt2char(OPT_COUNTERS)); - - break; - - - case 1: /* non option */ - if (optarg[0] == '!' && optarg[1] == '\0') { - if (invert) - xtables_error(PARAMETER_PROBLEM, - "multiple consecutive ! not" - " allowed"); - invert = TRUE; - optarg[0] = '\0'; - continue; - } - printf("Bad argument `%s'\n", optarg); - exit_tryhelp(2); - - default: - if (cs.target) { - xtables_option_tpcall(c, argv, - invert, cs.target, &cs.arp); - } - break; - } - invert = FALSE; - } - - if (cs.target) - xtables_option_tfcall(cs.target); - - if (optind < argc) - xtables_error(PARAMETER_PROBLEM, - "unknown arguments found on commandline"); - if (!command) - xtables_error(PARAMETER_PROBLEM, "no command specified"); - if (invert) - xtables_error(PARAMETER_PROBLEM, - "nothing appropriate following !"); - - if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { - if (!(options & OPT_D_IP)) - dhostnetworkmask = "0.0.0.0/0"; - if (!(options & OPT_S_IP)) - shostnetworkmask = "0.0.0.0/0"; - } - - if (shostnetworkmask) - parse_hostnetworkmask(shostnetworkmask, &saddrs, - &(cs.arp.arp.smsk), &nsaddrs); - - if (dhostnetworkmask) - parse_hostnetworkmask(dhostnetworkmask, &daddrs, - &(cs.arp.arp.tmsk), &ndaddrs); - - if ((nsaddrs > 1 || ndaddrs > 1) && - (cs.arp.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP))) - xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" - " source or destination IP addresses"); - - if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1)) - xtables_error(PARAMETER_PROBLEM, "Replacement rule does not " - "specify a unique address"); - - generic_opt_check(command, options); - - if (chain && strlen(chain) > ARPT_FUNCTION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "chain name `%s' too long (must be under %i chars)", - chain, ARPT_FUNCTION_MAXNAMELEN); - - if (command == CMD_APPEND - || command == CMD_DELETE - || command == CMD_INSERT - || command == CMD_REPLACE) { - if (strcmp(chain, "PREROUTING") == 0 - || strcmp(chain, "INPUT") == 0) { - /* -o not valid with incoming packets. */ - if (options & OPT_VIANAMEOUT) - xtables_error(PARAMETER_PROBLEM, - "Can't use -%c with %s\n", - opt2char(OPT_VIANAMEOUT), - chain); - } - - if (strcmp(chain, "POSTROUTING") == 0 - || strcmp(chain, "OUTPUT") == 0) { - /* -i not valid with outgoing packets */ - if (options & OPT_VIANAMEIN) - xtables_error(PARAMETER_PROBLEM, - "Can't use -%c with %s\n", - opt2char(OPT_VIANAMEIN), - chain); - } - } - - switch (command) { - case CMD_APPEND: - ret = append_entry(h, chain, *table, &cs, 0, - nsaddrs, saddrs, ndaddrs, daddrs, - options&OPT_VERBOSE, true); - break; - case CMD_DELETE: - ret = delete_entry(chain, *table, &cs, - nsaddrs, saddrs, ndaddrs, daddrs, - options&OPT_VERBOSE, h); - break; - case CMD_DELETE_NUM: - ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose); - break; - case CMD_REPLACE: - ret = replace_entry(chain, *table, &cs, rulenum - 1, - saddrs, daddrs, options&OPT_VERBOSE, h); - break; - case CMD_INSERT: - ret = append_entry(h, chain, *table, &cs, rulenum - 1, - nsaddrs, saddrs, ndaddrs, daddrs, - options&OPT_VERBOSE, false); - break; - case CMD_LIST: - ret = list_entries(h, chain, *table, - rulenum, - options&OPT_VERBOSE, - options&OPT_NUMERIC, - /*options&OPT_EXPANDED*/0, - options&OPT_LINENUMBERS); - break; - case CMD_FLUSH: - ret = nft_rule_flush(h, chain, *table, options & OPT_VERBOSE); - break; - case CMD_ZERO: - ret = nft_chain_zero_counters(h, chain, *table, - options & OPT_VERBOSE); - break; - case CMD_LIST|CMD_ZERO: - ret = list_entries(h, chain, *table, rulenum, - options&OPT_VERBOSE, - options&OPT_NUMERIC, - /*options&OPT_EXPANDED*/0, - options&OPT_LINENUMBERS); - if (ret) - ret = nft_chain_zero_counters(h, chain, *table, - options & OPT_VERBOSE); - break; - case CMD_NEW_CHAIN: - ret = nft_chain_user_add(h, chain, *table); - break; - case CMD_DELETE_CHAIN: - ret = nft_chain_user_del(h, chain, *table, - options & OPT_VERBOSE); - break; - case CMD_RENAME_CHAIN: - ret = nft_chain_user_rename(h, chain, *table, newname); - break; - case CMD_SET_POLICY: - ret = nft_chain_set(h, *table, chain, policy, NULL); - if (ret < 0) - xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n", - policy); - break; - default: - /* We should never reach this... */ - exit_tryhelp(2); - } - - if (nsaddrs) - free(saddrs); - if (ndaddrs) - free(daddrs); - - if (cs.target) - free(cs.target->t); - - xtables_free_opts(1); - -/* if (verbose > 1) - dump_entries(*handle);*/ - - return ret; -} |