summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-10-09 13:34:55 +0200
committerPhil Sutter <phil@nwl.cc>2024-01-10 16:07:31 +0100
commitdc5e6831b88fa28e141525eec4a0d5267024d3f7 (patch)
tree10597f6b1696e6717e142be94cc5d0a80566c286 /extensions
parentfa1f5ff52580f805cf5dc6190bd4da8ff5afe8e5 (diff)
extensions: libebt_ip: Use guided option parser
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libebt_ip.c199
-rw-r--r--extensions/libebt_ip.t8
2 files changed, 84 insertions, 123 deletions
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 97ec4160..350dbcb6 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -16,7 +16,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
#include <netdb.h>
#include <inttypes.h>
#include <xtables.h>
@@ -24,30 +23,56 @@
#include "libxt_icmp.h"
-#define IP_SOURCE '1'
-#define IP_DEST '2'
-#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
-#define IP_PROTO '4'
-#define IP_SPORT '5'
-#define IP_DPORT '6'
-#define IP_EBT_ICMP '7'
-#define IP_EBT_IGMP '8'
-
-static const struct option brip_opts[] = {
- { .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
- { .name = "ip-destination", .has_arg = true, .val = IP_DEST },
- { .name = "ip-dst", .has_arg = true, .val = IP_DEST },
- { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
- { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
- { .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
- { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
- { .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
- { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
- { .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
- { .name = "ip-icmp-type", .has_arg = true, .val = IP_EBT_ICMP },
- { .name = "ip-igmp-type", .has_arg = true, .val = IP_EBT_IGMP },
- XT_GETOPT_TABLEEND,
+/* must correspond to the bit position in EBT_IP6_* defines */
+enum {
+ O_SOURCE = 0,
+ O_DEST,
+ O_TOS,
+ O_PROTO,
+ O_SPORT,
+ O_DPORT,
+ O_ICMP,
+ O_IGMP,
+ F_PORT = 1 << O_ICMP | 1 << O_IGMP,
+ F_ICMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_IGMP,
+ F_IGMP = 1 << O_SPORT | 1 << O_DPORT | 1 << O_ICMP,
+};
+
+static const struct xt_option_entry brip_opts[] = {
+ { .name = "ip-source", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-src", .id = O_SOURCE, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-destination", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-dst", .id = O_DEST, .type = XTTYPE_HOSTMASK,
+ .flags = XTOPT_INVERT },
+ { .name = "ip-tos", .id = O_TOS, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, tos) },
+ { .name = "ip-protocol", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+ .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, protocol) },
+ { .name = "ip-source-port", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-sport", .id = O_SPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, sport) },
+ { .name = "ip-destination-port",.id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-dport", .id = O_DPORT, .type = XTTYPE_PORTRC,
+ .excl = F_PORT, .flags = XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(struct ebt_ip_info, dport) },
+ { .name = "ip-icmp-type", .id = O_ICMP, .type = XTTYPE_STRING,
+ .excl = F_ICMP, .flags = XTOPT_INVERT },
+ { .name = "ip-igmp-type", .id = O_IGMP, .type = XTTYPE_STRING,
+ .excl = F_IGMP, .flags = XTOPT_INVERT },
+ XTOPT_TABLEEND,
};
static void brip_print_help(void)
@@ -69,30 +94,6 @@ static void brip_print_help(void)
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
}
-static void
-parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = xtables_strdup(portstring);
-
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
- ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
-
- if (ports[0] > ports[1])
- xtables_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
/* original code from ebtables: useful_functions.c */
static void print_icmp_code(uint8_t *code)
{
@@ -130,86 +131,38 @@ static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
print_icmp_code(code);
}
-static int
-brip_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void brip_parse(struct xt_option_call *cb)
{
- struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
- struct in_addr *ipaddr, ipmask;
- unsigned int ipnr;
-
- switch (c) {
- case IP_SOURCE:
- if (invert)
- info->invflags |= EBT_IP_SOURCE;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->saddr = ipaddr->s_addr;
- info->smsk = ipmask.s_addr;
- free(ipaddr);
- info->bitmask |= EBT_IP_SOURCE;
- break;
- case IP_DEST:
- if (invert)
- info->invflags |= EBT_IP_DEST;
- xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
- info->daddr = ipaddr->s_addr;
- info->dmsk = ipmask.s_addr;
- free(ipaddr);
- info->bitmask |= EBT_IP_DEST;
- break;
- case IP_SPORT:
- if (invert)
- info->invflags |= EBT_IP_SPORT;
- parse_port_range(NULL, optarg, info->sport);
- info->bitmask |= EBT_IP_SPORT;
- break;
- case IP_DPORT:
- if (invert)
- info->invflags |= EBT_IP_DPORT;
- parse_port_range(NULL, optarg, info->dport);
- info->bitmask |= EBT_IP_DPORT;
- break;
- case IP_EBT_ICMP:
- if (invert)
- info->invflags |= EBT_IP_ICMP;
- ebt_parse_icmp(optarg, info->icmp_type, info->icmp_code);
- info->bitmask |= EBT_IP_ICMP;
+ struct ebt_ip_info *info = cb->data;
+
+ xtables_option_parse(cb);
+
+ info->bitmask |= 1 << cb->entry->id;
+ info->invflags |= cb->invert ? 1 << cb->entry->id : 0;
+
+ switch (cb->entry->id) {
+ case O_SOURCE:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->saddr = cb->val.haddr.ip;
+ info->smsk = cb->val.hmask.ip;
break;
- case IP_EBT_IGMP:
- if (invert)
- info->invflags |= EBT_IP_IGMP;
- ebt_parse_igmp(optarg, info->igmp_type);
- info->bitmask |= EBT_IP_IGMP;
+ case O_DEST:
+ cb->val.haddr.all[0] &= cb->val.hmask.all[0];
+ info->daddr = cb->val.haddr.ip;
+ info->dmsk = cb->val.hmask.ip;
break;
- case IP_EBT_TOS: {
- uintmax_t tosvalue;
-
- if (invert)
- info->invflags |= EBT_IP_TOS;
- if (!xtables_strtoul(optarg, NULL, &tosvalue, 0, 255))
- xtables_error(PARAMETER_PROBLEM,
- "Problem with specified IP tos");
- info->tos = tosvalue;
- info->bitmask |= EBT_IP_TOS;
- }
+ case O_ICMP:
+ ebt_parse_icmp(cb->arg, info->icmp_type, info->icmp_code);
break;
- case IP_PROTO:
- if (invert)
- info->invflags |= EBT_IP_PROTO;
- info->protocol = xtables_parse_protocol(optarg);
- info->bitmask |= EBT_IP_PROTO;
+ case O_IGMP:
+ ebt_parse_igmp(cb->arg, info->igmp_type);
break;
- default:
- return 0;
}
-
- *flags |= info->bitmask;
- return 1;
}
-static void brip_final_check(unsigned int flags)
+static void brip_final_check(struct xt_fcheck_call *fc)
{
- if (!flags)
+ if (!fc->xflags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
@@ -496,11 +449,11 @@ static struct xtables_match brip_match = {
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
.help = brip_print_help,
- .parse = brip_parse,
- .final_check = brip_final_check,
+ .x6_parse = brip_parse,
+ .x6_fcheck = brip_final_check,
.print = brip_print,
.xlate = brip_xlate,
- .extra_opts = brip_opts,
+ .x6_options = brip_opts,
};
void _init(void)
diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t
index 8be5dfbb..f6012df4 100644
--- a/extensions/libebt_ip.t
+++ b/extensions/libebt_ip.t
@@ -1,13 +1,21 @@
:INPUT,FORWARD,OUTPUT
-p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 --ip-src ! 192.168.0.0/24 -j ACCEPT;OK
-p IPv4 --ip-dst 10.0.0.1;=;OK
+-p IPv4 --ip-dst ! 10.0.0.1;=;OK
-p IPv4 --ip-tos 0xFF;=;OK
-p IPv4 --ip-tos ! 0xFF;=;OK
-p IPv4 --ip-proto tcp --ip-dport 22;=;OK
-p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK
-p IPv4 --ip-proto 253;=;OK
+-p IPv4 --ip-proto ! 253;=;OK
-p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK
-p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK
-p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp --ip-icmp-type ! 1:10/0:255 -j CONTINUE;OK
--ip-proto icmp --ip-icmp-type 1/1;=;FAIL
! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL
+! -p ip --ip-proto tcp --ip-sport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-sport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-icmp-type echo-reply;;FAIL
+! -p ip --ip-proto tcp --ip-dport 22 --ip-igmp-type membership-query;;FAIL
+! -p ip --ip-proto icmp --ip-icmp-type echo-reply --ip-igmp-type membership-query;;FAIL
+-p IPv4 --ip-proto icmp --ip-icmp-type ! echo-reply;=;OK