summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libip6t_mh.c44
-rw-r--r--extensions/libip6t_rt.c159
-rw-r--r--extensions/libipt_CLUSTERIP.c157
-rw-r--r--extensions/libipt_DNAT.c88
-rw-r--r--extensions/libipt_MASQUERADE.c48
-rw-r--r--extensions/libipt_REDIRECT.c62
-rw-r--r--extensions/libipt_SAME.c82
-rw-r--r--extensions/libipt_SNAT.c88
-rw-r--r--extensions/libxt_iprange.c144
-rw-r--r--extensions/libxt_mac.c80
-rw-r--r--include/xtables.h.in3
-rw-r--r--xtoptions.c26
12 files changed, 370 insertions, 611 deletions
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
index 460f9e47..686a2932 100644
--- a/extensions/libip6t_mh.c
+++ b/extensions/libip6t_mh.c
@@ -11,15 +11,17 @@
*
* Based on libip6t_{icmpv6,udp}.c
*/
-#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_mh.h>
+enum {
+ O_MH_TYPE = 0,
+};
+
struct mh_name {
const char *name;
uint8_t type;
@@ -122,27 +124,14 @@ static void parse_mh_types(const char *mhtype, uint8_t *types)
free(buffer);
}
-#define MH_TYPES 0x01
-
-static int mh_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void mh_parse(struct xt_option_call *cb)
{
- struct ip6t_mh *mhinfo = (struct ip6t_mh *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & MH_TYPES)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--mh-type' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_mh_types(optarg, mhinfo->types);
- if (invert)
- mhinfo->invflags |= IP6T_MH_INV_TYPE;
- *flags |= MH_TYPES;
- break;
- }
+ struct ip6t_mh *mhinfo = cb->data;
- return 1;
+ xtables_option_parse(cb);
+ parse_mh_types(cb->arg, mhinfo->types);
+ if (cb->invert)
+ mhinfo->invflags |= IP6T_MH_INV_TYPE;
}
static const char *type_to_name(uint8_t type)
@@ -213,9 +202,10 @@ static void mh_save(const void *ip, const struct xt_entry_match *match)
printf(" --mh-type %u", mhinfo->types[0]);
}
-static const struct option mh_opts[] = {
- {.name = "mh-type", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry mh_opts[] = {
+ {.name = "mh-type", .id = O_MH_TYPE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
static struct xtables_match mh_mt6_reg = {
@@ -226,10 +216,10 @@ static struct xtables_match mh_mt6_reg = {
.userspacesize = XT_ALIGN(sizeof(struct ip6t_mh)),
.help = mh_help,
.init = mh_init,
- .parse = mh_parse,
+ .x6_parse = mh_parse,
.print = mh_print,
.save = mh_save,
- .extra_opts = mh_opts,
+ .x6_options = mh_opts,
};
void _init(void)
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index 1c57dbd6..11bfda92 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -1,19 +1,20 @@
-/* Shared library add-on to ip6tables to add Routing header support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
-#include <errno.h>
#include <xtables.h>
-/*#include <linux/in6.h>*/
#include <linux/netfilter_ipv6/ip6t_rt.h>
-#include <sys/types.h>
-#include <sys/socket.h>
#include <arpa/inet.h>
-/*#define DEBUG 1*/
+enum {
+ O_RT_TYPE = 0,
+ O_RT_SEGSLEFT,
+ O_RT_LEN,
+ O_RT0RES,
+ O_RT0ADDRS,
+ O_RT0NSTRICT,
+ F_RT_TYPE = 1 << O_RT_TYPE,
+ F_RT0ADDRS = 1 << O_RT0ADDRS,
+};
static void rt_help(void)
{
@@ -28,58 +29,20 @@ static void rt_help(void)
IP6T_RT_HOPS);
}
-static const struct option rt_opts[] = {
- {.name = "rt-type", .has_arg = true, .val = '1'},
- {.name = "rt-segsleft", .has_arg = true, .val = '2'},
- {.name = "rt-len", .has_arg = true, .val = '3'},
- {.name = "rt-0-res", .has_arg = false, .val = '4'},
- {.name = "rt-0-addrs", .has_arg = true, .val = '5'},
- {.name = "rt-0-not-strict", .has_arg = false, .val = '6'},
- XT_GETOPT_TABLEEND,
+#define s struct ip6t_rt
+static const struct xt_option_entry rt_opts[] = {
+ {.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32RC,
+ .flags = XTOPT_INVERT},
+ {.name = "rt-segsleft", .id = O_RT_SEGSLEFT, .type = XTTYPE_UINT32RC,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segsleft)},
+ {.name = "rt-len", .id = O_RT_LEN, .type = XTTYPE_UINT32,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
+ {.name = "rt-0-res", .id = O_RT0RES, .type = XTTYPE_NONE},
+ {.name = "rt-0-addrs", .id = O_RT0ADDRS, .type = XTTYPE_STRING},
+ {.name = "rt-0-not-strict", .id = O_RT0NSTRICT, .type = XTTYPE_STRING},
+ XTOPT_TABLEEND,
};
-
-static uint32_t
-parse_rt_num(const char *idstr, const char *typestr)
-{
- unsigned long int id;
- char* ep;
-
- id = strtoul(idstr,&ep,0) ;
-
- if ( idstr == ep ) {
- xtables_error(PARAMETER_PROBLEM,
- "RT no valid digits in %s `%s'", typestr, idstr);
- }
- if ( id == ULONG_MAX && errno == ERANGE ) {
- xtables_error(PARAMETER_PROBLEM,
- "%s `%s' specified too big: would overflow",
- typestr, idstr);
- }
- if ( *idstr != '\0' && *ep != '\0' ) {
- xtables_error(PARAMETER_PROBLEM,
- "RT error parsing %s `%s'", typestr, idstr);
- }
- return id;
-}
-
-static void
-parse_rt_segsleft(const char *idstring, uint32_t *ids)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(idstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ids[0] = ids[1] = parse_rt_num(buffer,"segsleft");
- else {
- *cp = '\0';
- cp++;
-
- ids[0] = buffer[0] ? parse_rt_num(buffer,"segsleft") : 0;
- ids[1] = cp[0] ? parse_rt_num(cp,"segsleft") : 0xFFFFFFFF;
- }
- free(buffer);
-}
+#undef s
static const char *
addr_to_numeric(const struct in6_addr *addrp)
@@ -143,83 +106,49 @@ static void rt_init(struct xt_entry_match *m)
rtinfo->segsleft[1] = 0xFFFFFFFF;
}
-static int rt_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void rt_parse(struct xt_option_call *cb)
{
- struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data;
+ struct ip6t_rt *rtinfo = cb->data;
- switch (c) {
- case '1':
- if (*flags & IP6T_RT_TYP)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-type' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- rtinfo->rt_type = parse_rt_num(optarg, "type");
- if (invert)
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_RT_TYPE:
+ if (cb->invert)
rtinfo->invflags |= IP6T_RT_INV_TYP;
rtinfo->flags |= IP6T_RT_TYP;
- *flags |= IP6T_RT_TYP;
break;
- case '2':
- if (*flags & IP6T_RT_SGS)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-segsleft' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_rt_segsleft(optarg, rtinfo->segsleft);
- if (invert)
+ case O_RT_SEGSLEFT:
+ if (cb->invert)
rtinfo->invflags |= IP6T_RT_INV_SGS;
rtinfo->flags |= IP6T_RT_SGS;
- *flags |= IP6T_RT_SGS;
break;
- case '3':
- if (*flags & IP6T_RT_LEN)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-len' allowed");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- rtinfo->hdrlen = parse_rt_num(optarg, "length");
- if (invert)
+ case O_RT_LEN:
+ if (cb->invert)
rtinfo->invflags |= IP6T_RT_INV_LEN;
rtinfo->flags |= IP6T_RT_LEN;
- *flags |= IP6T_RT_LEN;
break;
- case '4':
- if (*flags & IP6T_RT_RES)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-0-res' allowed");
- if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
+ case O_RT0RES:
+ if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
+ rtinfo->invflags & IP6T_RT_INV_TYP)
xtables_error(PARAMETER_PROBLEM,
"`--rt-type 0' required before `--rt-0-res'");
rtinfo->flags |= IP6T_RT_RES;
- *flags |= IP6T_RT_RES;
break;
- case '5':
- if (*flags & IP6T_RT_FST)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-0-addrs' allowed");
- if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
+ case O_RT0ADDRS:
+ if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
+ rtinfo->invflags & IP6T_RT_INV_TYP)
xtables_error(PARAMETER_PROBLEM,
"`--rt-type 0' required before `--rt-0-addrs'");
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- " '!' not allowed with `--rt-0-addrs'");
- rtinfo->addrnr = parse_addresses(optarg, rtinfo->addrs);
+ rtinfo->addrnr = parse_addresses(cb->arg, rtinfo->addrs);
rtinfo->flags |= IP6T_RT_FST;
- *flags |= IP6T_RT_FST;
break;
- case '6':
- if (*flags & IP6T_RT_FST_NSTRICT)
- xtables_error(PARAMETER_PROBLEM,
- "Only one `--rt-0-not-strict' allowed");
- if ( !(*flags & IP6T_RT_FST) )
+ case O_RT0NSTRICT:
+ if (!(cb->xflags & F_RT0ADDRS))
xtables_error(PARAMETER_PROBLEM,
"`--rt-0-addr ...' required before `--rt-0-not-strict'");
rtinfo->flags |= IP6T_RT_FST_NSTRICT;
- *flags |= IP6T_RT_FST_NSTRICT;
break;
}
-
- return 1;
}
static void
@@ -322,10 +251,10 @@ static struct xtables_match rt_mt6_reg = {
.userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)),
.help = rt_help,
.init = rt_init,
- .parse = rt_parse,
+ .x6_parse = rt_parse,
.print = rt_print,
.save = rt_save,
- .extra_opts = rt_opts,
+ .x6_options = rt_opts,
};
void
diff --git a/extensions/libipt_CLUSTERIP.c b/extensions/libipt_CLUSTERIP.c
index f7f46d1c..301e0e1d 100644
--- a/extensions/libipt_CLUSTERIP.c
+++ b/extensions/libipt_CLUSTERIP.c
@@ -19,6 +19,22 @@
#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
+enum {
+ O_NEW = 0,
+ O_HASHMODE,
+ O_CLUSTERMAC,
+ O_TOTAL_NODES,
+ O_LOCAL_NODE,
+ O_HASH_INIT,
+ F_NEW = 1 << O_NEW,
+ F_HASHMODE = 1 << O_HASHMODE,
+ F_CLUSTERMAC = 1 << O_CLUSTERMAC,
+ F_TOTAL_NODES = 1 << O_TOTAL_NODES,
+ F_LOCAL_NODE = 1 << O_LOCAL_NODE,
+ F_FULL = F_NEW | F_HASHMODE | F_CLUSTERMAC |
+ F_TOTAL_NODES | F_LOCAL_NODE,
+};
+
static void CLUSTERIP_help(void)
{
printf(
@@ -34,130 +50,61 @@ static void CLUSTERIP_help(void)
" --hash-init <num> Set init value of the Jenkins hash\n");
}
-#define PARAM_NEW 0x0001
-#define PARAM_HMODE 0x0002
-#define PARAM_MAC 0x0004
-#define PARAM_TOTALNODE 0x0008
-#define PARAM_LOCALNODE 0x0010
-#define PARAM_HASHINIT 0x0020
-
-static const struct option CLUSTERIP_opts[] = {
- {.name = "new", .has_arg = false, .val = '1'},
- {.name = "hashmode", .has_arg = true, .val = '2'},
- {.name = "clustermac", .has_arg = true, .val = '3'},
- {.name = "total-nodes", .has_arg = true, .val = '4'},
- {.name = "local-node", .has_arg = true, .val = '5'},
- {.name = "hash-init", .has_arg = true, .val = '6'},
- XT_GETOPT_TABLEEND,
+#define s struct ipt_clusterip_tgt_info
+static const struct xt_option_entry CLUSTERIP_opts[] = {
+ {.name = "new", .id = O_NEW, .type = XTTYPE_NONE},
+ {.name = "hashmode", .id = O_HASHMODE, .type = XTTYPE_STRING,
+ .also = O_NEW},
+ {.name = "clustermac", .id = O_CLUSTERMAC, .type = XTTYPE_ETHERMAC,
+ .also = O_NEW, .flags = XTOPT_PUT, XTOPT_POINTER(s, clustermac)},
+ {.name = "total-nodes", .id = O_TOTAL_NODES, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, num_total_nodes),
+ .also = O_NEW, .max = CLUSTERIP_MAX_NODES},
+ {.name = "local-node", .id = O_LOCAL_NODE, .type = XTTYPE_UINT16,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, local_nodes[0]),
+ .also = O_NEW, .max = CLUSTERIP_MAX_NODES},
+ {.name = "hash-init", .id = O_HASH_INIT, .type = XTTYPE_UINT32,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, hash_initval),
+ .also = O_NEW, .max = UINT_MAX},
+ XTOPT_TABLEEND,
};
+#undef s
-static void
-parse_mac(const char *mac, char *macbuf)
+static void CLUSTERIP_parse(struct xt_option_call *cb)
{
- unsigned int i = 0;
-
- if (strlen(mac) != ETH_ALEN*3-1)
- xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac);
-
- for (i = 0; i < ETH_ALEN; i++) {
- long number;
- char *end;
+ struct ipt_clusterip_tgt_info *cipinfo = cb->data;
- number = strtol(mac + i*3, &end, 16);
-
- if (end == mac + i*3 + 2
- && number >= 0
- && number <= 255)
- macbuf[i] = number;
- else
- xtables_error(PARAMETER_PROBLEM,
- "Bad mac address `%s'", mac);
- }
-}
-
-static int CLUSTERIP_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
-{
- struct ipt_clusterip_tgt_info *cipinfo
- = (struct ipt_clusterip_tgt_info *)(*target)->data;
-
- switch (c) {
- unsigned int num;
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_NEW:
cipinfo->flags |= CLUSTERIP_FLAG_NEW;
- if (*flags & PARAM_NEW)
- xtables_error(PARAMETER_PROBLEM, "Can only specify \"--new\" once\n");
- *flags |= PARAM_NEW;
break;
- case '2':
- if (!(*flags & PARAM_NEW))
- xtables_error(PARAMETER_PROBLEM, "Can only specify hashmode combined with \"--new\"\n");
- if (*flags & PARAM_HMODE)
- xtables_error(PARAMETER_PROBLEM, "Can only specify hashmode once\n");
- if (!strcmp(optarg, "sourceip"))
+ case O_HASHMODE:
+ if (strcmp(cb->arg, "sourceip") == 0)
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP;
- else if (!strcmp(optarg, "sourceip-sourceport"))
+ else if (strcmp(cb->arg, "sourceip-sourceport") == 0)
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT;
- else if (!strcmp(optarg, "sourceip-sourceport-destport"))
+ else if (strcmp(cb->arg, "sourceip-sourceport-destport") == 0)
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT_DPT;
else
xtables_error(PARAMETER_PROBLEM, "Unknown hashmode \"%s\"\n",
- optarg);
- *flags |= PARAM_HMODE;
+ cb->arg);
break;
- case '3':
- if (!(*flags & PARAM_NEW))
- xtables_error(PARAMETER_PROBLEM, "Can only specify MAC combined with \"--new\"\n");
- if (*flags & PARAM_MAC)
- xtables_error(PARAMETER_PROBLEM, "Can only specify MAC once\n");
- parse_mac(optarg, (char *)cipinfo->clustermac);
+ case O_CLUSTERMAC:
if (!(cipinfo->clustermac[0] & 0x01))
xtables_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
- *flags |= PARAM_MAC;
- break;
- case '4':
- if (!(*flags & PARAM_NEW))
- xtables_error(PARAMETER_PROBLEM, "Can only specify node number combined with \"--new\"\n");
- if (*flags & PARAM_TOTALNODE)
- xtables_error(PARAMETER_PROBLEM, "Can only specify total node number once\n");
- if (!xtables_strtoui(optarg, NULL, &num, 1, CLUSTERIP_MAX_NODES))
- xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
- cipinfo->num_total_nodes = num;
- *flags |= PARAM_TOTALNODE;
break;
- case '5':
- if (!(*flags & PARAM_NEW))
- xtables_error(PARAMETER_PROBLEM, "Can only specify node number combined with \"--new\"\n");
- if (*flags & PARAM_LOCALNODE)
- xtables_error(PARAMETER_PROBLEM, "Can only specify local node number once\n");
- if (!xtables_strtoui(optarg, NULL, &num, 1, CLUSTERIP_MAX_NODES))
- xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
+ case O_LOCAL_NODE:
cipinfo->num_local_nodes = 1;
- cipinfo->local_nodes[0] = num;
- *flags |= PARAM_LOCALNODE;
- break;
- case '6':
- if (!(*flags & PARAM_NEW))
- xtables_error(PARAMETER_PROBLEM, "Can only specify hash init value combined with \"--new\"\n");
- if (*flags & PARAM_HASHINIT)
- xtables_error(PARAMETER_PROBLEM, "Can specify hash init value only once\n");
- if (!xtables_strtoui(optarg, NULL, &num, 0, UINT_MAX))
- xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
- cipinfo->hash_initval = num;
- *flags |= PARAM_HASHINIT;
break;
}
-
- return 1;
}
-static void CLUSTERIP_check(unsigned int flags)
+static void CLUSTERIP_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (cb->xflags == 0)
return;
-
- if ((flags & (PARAM_NEW|PARAM_HMODE|PARAM_MAC|PARAM_TOTALNODE|PARAM_LOCALNODE))
- == (PARAM_NEW|PARAM_HMODE|PARAM_MAC|PARAM_TOTALNODE|PARAM_LOCALNODE))
+ if ((cb->xflags & F_FULL) == F_FULL)
return;
xtables_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
@@ -235,11 +182,11 @@ static struct xtables_target clusterip_tg_reg = {
.size = XT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)),
.userspacesize = offsetof(struct ipt_clusterip_tgt_info, config),
.help = CLUSTERIP_help,
- .parse = CLUSTERIP_parse,
- .final_check = CLUSTERIP_check,
+ .x6_parse = CLUSTERIP_parse,
+ .x6_fcheck = CLUSTERIP_check,
.print = CLUSTERIP_print,
.save = CLUSTERIP_save,
- .extra_opts = CLUSTERIP_opts,
+ .x6_options = CLUSTERIP_opts,
};
void _init(void)
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index 6eedca10..6a46f109 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -1,18 +1,20 @@
-/* Shared library add-on to iptables to add destination-NAT support. */
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <iptables.h> /* get_kernel_version */
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_nat.h>
-#define IPT_DNAT_OPT_DEST 0x1
-#define IPT_DNAT_OPT_RANDOM 0x2
+enum {
+ O_TO_DEST = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ F_TO_DEST = 1 << O_TO_DEST,
+ F_RANDOM = 1 << O_RANDOM,
+};
/* Dest NAT data consists of a multi-range, indicating where to map
to. */
@@ -31,11 +33,12 @@ static void DNAT_help(void)
"[--random] [--persistent]\n");
}
-static const struct option DNAT_opts[] = {
- {.name = "to-destination", .has_arg = true, .val = '1'},
- {.name = "random", .has_arg = false, .val = '2'},
- {.name = "persistent", .has_arg = false, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry DNAT_opts[] = {
+ {.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_MULTI},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
static struct ipt_natinfo *
@@ -59,12 +62,15 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
/* Ranges expected in network order. */
static struct xt_entry_target *
-parse_to(char *arg, int portok, struct ipt_natinfo *info)
+parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
struct nf_nat_range range;
- char *colon, *dash, *error;
+ char *arg, *colon, *dash, *error;
const struct in_addr *ip;
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
memset(&range, 0, sizeof(range));
colon = strchr(arg, ':');
@@ -107,8 +113,10 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
range.max.tcp.port = htons(maxport);
}
/* Starts with a colon? No IP info...*/
- if (colon == arg)
+ if (colon == arg) {
+ free(arg);
return &(append_range(info, &range)->t);
+ }
*colon = '\0';
}
@@ -134,14 +142,14 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
} else
range.max_ip = range.min_ip;
+ free(arg);
return &(append_range(info, &range)->t);
}
-static int DNAT_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_target **target)
+static void DNAT_parse(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
- struct ipt_natinfo *info = (void *)*target;
+ const struct ipt_entry *entry = cb->xt_entry;
+ struct ipt_natinfo *info = (void *)(*cb->target);
int portok;
if (entry->ip.proto == IPPROTO_TCP
@@ -153,46 +161,29 @@ static int DNAT_parse(int c, char **argv, int invert, unsigned int *flags,
else
portok = 0;
- switch (c) {
- case '1':
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --to-destination");
-
- if (*flags & IPT_DNAT_OPT_DEST) {
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_DEST:
+ if (cb->xflags & F_TO_DEST) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
xtables_error(PARAMETER_PROBLEM,
"Multiple --to-destination not supported");
}
- *target = parse_to(optarg, portok, info);
+ *cb->target = parse_to(cb->arg, portok, info);
/* WTF do we need this for?? */
- if (*flags & IPT_DNAT_OPT_RANDOM)
+ if (cb->xflags & F_RANDOM)
info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_DNAT_OPT_DEST;
- return 1;
-
- case '2':
- if (*flags & IPT_DNAT_OPT_DEST) {
+ break;
+ case O_RANDOM:
+ if (cb->xflags & F_TO_DEST)
info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_DNAT_OPT_RANDOM;
- } else
- *flags |= IPT_DNAT_OPT_RANDOM;
- return 1;
-
- case '3':
+ break;
+ case O_PERSISTENT:
info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
- return 1;
+ break;
}
- return 0;
-}
-
-static void DNAT_check(unsigned int flags)
-{
- if (!(flags & IPT_DNAT_OPT_DEST))
- xtables_error(PARAMETER_PROBLEM,
- "You must specify --to-destination");
}
static void print_range(const struct nf_nat_range *r)
@@ -253,11 +244,10 @@ static struct xtables_target dnat_tg_reg = {
.size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.help = DNAT_help,
- .parse = DNAT_parse,
- .final_check = DNAT_check,
+ .x6_parse = DNAT_parse,
.print = DNAT_print,
.save = DNAT_save,
- .extra_opts = DNAT_opts,
+ .x6_options = DNAT_opts,
};
void _init(void)
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
index 00baf25e..7ba42dfd 100644
--- a/extensions/libipt_MASQUERADE.c
+++ b/extensions/libipt_MASQUERADE.c
@@ -1,5 +1,3 @@
-/* Shared library add-on to iptables to add masquerade support. */
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
@@ -10,6 +8,11 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_nat.h>
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+};
+
static void MASQUERADE_help(void)
{
printf(
@@ -20,10 +23,10 @@ static void MASQUERADE_help(void)
" Randomize source port.\n");
}
-static const struct option MASQUERADE_opts[] = {
- {.name = "to-ports", .has_arg = true, .val = '1'},
- {.name = "random", .has_arg = false, .val = '2'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry MASQUERADE_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
static void MASQUERADE_init(struct xt_entry_target *t)
@@ -32,7 +35,6 @@ static void MASQUERADE_init(struct xt_entry_target *t)
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
-
}
/* Parses ports */
@@ -69,13 +71,11 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr)
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
}
-static int MASQUERADE_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_target **target)
+static void MASQUERADE_parse(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
+ const struct ipt_entry *entry = cb->xt_entry;
int portok;
- struct nf_nat_multi_range *mr
- = (struct nf_nat_multi_range *)(*target)->data;
+ struct nf_nat_multi_range *mr = cb->data;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
@@ -86,24 +86,18 @@ static int MASQUERADE_parse(int c, char **argv, int invert, unsigned int *flags,
else
portok = 0;
- switch (c) {
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
if (!portok)
xtables_error(PARAMETER_PROBLEM,
"Need TCP, UDP, SCTP or DCCP with port specification");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --to-ports");
-
- parse_ports(optarg, mr);
- return 1;
-
- case '2':
+ parse_ports(cb->arg, mr);
+ break;
+ case O_RANDOM:
mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- return 1;
+ break;
}
- return 0;
}
static void
@@ -148,10 +142,10 @@ static struct xtables_target masquerade_tg_reg = {
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.help = MASQUERADE_help,
.init = MASQUERADE_init,
- .parse = MASQUERADE_parse,
+ .x6_parse = MASQUERADE_parse,
.print = MASQUERADE_print,
.save = MASQUERADE_save,
- .extra_opts = MASQUERADE_opts,
+ .x6_options = MASQUERADE_opts,
};
void _init(void)
diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c
index 471ff29a..426a7463 100644
--- a/extensions/libipt_REDIRECT.c
+++ b/extensions/libipt_REDIRECT.c
@@ -1,17 +1,17 @@
-/* Shared library add-on to iptables to add redirect support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_nat.h>
-#define IPT_REDIRECT_OPT_DEST 0x01
-#define IPT_REDIRECT_OPT_RANDOM 0x02
+enum {
+ O_TO_PORTS = 0,
+ O_RANDOM,
+ F_TO_PORTS = 1 << O_TO_PORTS,
+ F_RANDOM = 1 << O_RANDOM,
+};
static void REDIRECT_help(void)
{
@@ -22,10 +22,11 @@ static void REDIRECT_help(void)
" [--random]\n");
}
-static const struct option REDIRECT_opts[] = {
- {.name = "to-ports", .has_arg = true, .val = '1'},
- {.name = "random", .has_arg = false, .val = '2'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry REDIRECT_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
static void REDIRECT_init(struct xt_entry_target *t)
@@ -34,7 +35,6 @@ static void REDIRECT_init(struct xt_entry_target *t)
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
-
}
/* Parses ports */
@@ -73,12 +73,10 @@ parse_ports(const char *arg, struct nf_nat_multi_range *mr)
xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
}
-static int REDIRECT_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_target **target)
+static void REDIRECT_parse(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
- struct nf_nat_multi_range *mr
- = (struct nf_nat_multi_range *)(*target)->data;
+ const struct ipt_entry *entry = cb->xt_entry;
+ struct nf_nat_multi_range *mr = (void *)(*cb->target)->data;
int portok;
if (entry->ip.proto == IPPROTO_TCP
@@ -90,31 +88,21 @@ static int REDIRECT_parse(int c, char **argv, int invert, unsigned int *flags,
else
portok = 0;
- switch (c) {
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_PORTS:
if (!portok)
xtables_error(PARAMETER_PROBLEM,
"Need TCP, UDP, SCTP or DCCP with port specification");
-
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --to-ports");
-
- parse_ports(optarg, mr);
- if (*flags & IPT_REDIRECT_OPT_RANDOM)
+ parse_ports(cb->arg, mr);
+ if (cb->xflags & F_RANDOM)
mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_REDIRECT_OPT_DEST;
- return 1;
-
- case '2':
- if (*flags & IPT_REDIRECT_OPT_DEST) {
+ break;
+ case O_RANDOM:
+ if (cb->xflags & F_TO_PORTS)
mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_REDIRECT_OPT_RANDOM;
- } else
- *flags |= IPT_REDIRECT_OPT_RANDOM;
- return 1;
+ break;
}
- return 0;
}
static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
@@ -156,10 +144,10 @@ static struct xtables_target redirect_tg_reg = {
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.help = REDIRECT_help,
.init = REDIRECT_init,
- .parse = REDIRECT_parse,
+ .x6_parse = REDIRECT_parse,
.print = REDIRECT_print,
.save = REDIRECT_save,
- .extra_opts = REDIRECT_opts,
+ .x6_options = REDIRECT_opts,
};
void _init(void)
diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c
index b18351e8..2ff6c82e 100644
--- a/extensions/libipt_SAME.c
+++ b/extensions/libipt_SAME.c
@@ -1,15 +1,17 @@
-/* Shared library add-on to iptables to add simple non load-balancing SNAT support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <net/netfilter/nf_nat.h>
-/* For 64bit kernel / 32bit userspace */
#include <linux/netfilter_ipv4/ipt_SAME.h>
+enum {
+ O_TO_ADDR = 0,
+ O_NODST,
+ O_RANDOM,
+ F_RANDOM = 1 << O_RANDOM,
+};
+
static void SAME_help(void)
{
printf(
@@ -25,20 +27,23 @@ static void SAME_help(void)
" Randomize source port\n");
}
-static const struct option SAME_opts[] = {
- {.name = "to", .has_arg = true, .val = '1'},
- {.name = "nodst", .has_arg = false, .val = '2'},
- {.name = "random", .has_arg = false, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry SAME_opts[] = {
+ {.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
+ {.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
/* Parses range of IPs */
-static void
-parse_to(char *arg, struct nf_nat_range *range)
+static void parse_to(const char *orig_arg, struct nf_nat_range *range)
{
- char *dash;
+ char *dash, *arg;
const struct in_addr *ip;
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
range->flags |= IP_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
@@ -62,63 +67,37 @@ parse_to(char *arg, struct nf_nat_range *range)
if (range->min_ip > range->max_ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
arg, dash+1);
+ free(arg);
}
-#define IPT_SAME_OPT_TO 0x01
-#define IPT_SAME_OPT_NODST 0x02
-#define IPT_SAME_OPT_RANDOM 0x04
-
-static int SAME_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_target **target)
+static void SAME_parse(struct xt_option_call *cb)
{
- struct ipt_same_info *mr
- = (struct ipt_same_info *)(*target)->data;
+ struct ipt_same_info *mr = cb->data;
unsigned int count;
- switch (c) {
- case '1':
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_ADDR:
if (mr->rangesize == IPT_SAME_MAX_RANGE)
xtables_error(PARAMETER_PROBLEM,
"Too many ranges specified, maximum "
"is %i ranges.\n",
IPT_SAME_MAX_RANGE);
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --to");
-
- parse_to(optarg, &mr->range[mr->rangesize]);
+ parse_to(cb->arg, &mr->range[mr->rangesize]);
/* WTF do we need this for? */
- if (*flags & IPT_SAME_OPT_RANDOM)
+ if (cb->xflags & F_RANDOM)
mr->range[mr->rangesize].flags
|= IP_NAT_RANGE_PROTO_RANDOM;
mr->rangesize++;
- *flags |= IPT_SAME_OPT_TO;
break;
-
- case '2':
- if (*flags & IPT_SAME_OPT_NODST)
- xtables_error(PARAMETER_PROBLEM,
- "Can't specify --nodst twice");
-
+ case O_NODST:
mr->info |= IPT_SAME_NODST;
- *flags |= IPT_SAME_OPT_NODST;
break;
-
- case '3':
- *flags |= IPT_SAME_OPT_RANDOM;
+ case O_RANDOM:
for (count=0; count < mr->rangesize; count++)
mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
break;
}
-
- return 1;
-}
-
-static void SAME_check(unsigned int flags)
-{
- if (!(flags & IPT_SAME_OPT_TO))
- xtables_error(PARAMETER_PROBLEM,
- "SAME needs --to");
}
static void SAME_print(const void *ip, const struct xt_entry_target *target,
@@ -186,11 +165,10 @@ static struct xtables_target same_tg_reg = {
.size = XT_ALIGN(sizeof(struct ipt_same_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)),
.help = SAME_help,
- .parse = SAME_parse,
- .final_check = SAME_check,
+ .x6_parse = SAME_parse,
.print = SAME_print,
.save = SAME_save,
- .extra_opts = SAME_opts,
+ .x6_options = SAME_opts,
};
void _init(void)
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index 1a009548..9156a7b7 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -1,18 +1,20 @@
-/* Shared library add-on to iptables to add source-NAT support. */
-#include <stdbool.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
#include <xtables.h>
#include <iptables.h>
#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_nat.h>
-#define IPT_SNAT_OPT_SOURCE 0x01
-#define IPT_SNAT_OPT_RANDOM 0x02
+enum {
+ O_TO_SRC = 0,
+ O_RANDOM,
+ O_PERSISTENT,
+ F_TO_SRC = 1 << O_TO_SRC,
+ F_RANDOM = 1 << O_RANDOM,
+};
/* Source NAT data consists of a multi-range, indicating where to map
to. */
@@ -31,11 +33,12 @@ static void SNAT_help(void)
"[--random] [--persistent]\n");
}
-static const struct option SNAT_opts[] = {
- {.name = "to-source", .has_arg = true, .val = '1'},
- {.name = "random", .has_arg = false, .val = '2'},
- {.name = "persistent", .has_arg = false, .val = '3'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry SNAT_opts[] = {
+ {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND | XTOPT_MULTI},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
};
static struct ipt_natinfo *
@@ -59,12 +62,15 @@ append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
/* Ranges expected in network order. */
static struct xt_entry_target *
-parse_to(char *arg, int portok, struct ipt_natinfo *info)
+parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
{
struct nf_nat_range range;
- char *colon, *dash, *error;
+ char *arg, *colon, *dash, *error;
const struct in_addr *ip;
+ arg = strdup(orig_arg);
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
memset(&range, 0, sizeof(range));
colon = strchr(arg, ':');
@@ -107,8 +113,10 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
range.max.tcp.port = htons(maxport);
}
/* Starts with a colon? No IP info...*/
- if (colon == arg)
+ if (colon == arg) {
+ free(arg);
return &(append_range(info, &range)->t);
+ }
*colon = '\0';
}
@@ -134,14 +142,14 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
} else
range.max_ip = range.min_ip;
+ free(arg);
return &(append_range(info, &range)->t);
}
-static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_target **target)
+static void SNAT_parse(struct xt_option_call *cb)
{
- const struct ipt_entry *entry = e;
- struct ipt_natinfo *info = (void *)*target;
+ const struct ipt_entry *entry = cb->xt_entry;
+ struct ipt_natinfo *info = (void *)(*cb->target);
int portok;
if (entry->ip.proto == IPPROTO_TCP
@@ -153,46 +161,29 @@ static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags,
else
portok = 0;
- switch (c) {
- case '1':
- if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
- xtables_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --to-source");
-
- if (*flags & IPT_SNAT_OPT_SOURCE) {
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_TO_SRC:
+ if (cb->xflags & F_TO_SRC) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
xtables_error(PARAMETER_PROBLEM,
"Multiple --to-source not supported");
}
- *target = parse_to(optarg, portok, info);
+ *cb->target = parse_to(cb->arg, portok, info);
/* WTF do we need this for?? */
- if (*flags & IPT_SNAT_OPT_RANDOM)
+ if (cb->xflags & F_RANDOM)
info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_SNAT_OPT_SOURCE;
- return 1;
-
- case '2':
- if (*flags & IPT_SNAT_OPT_SOURCE) {
+ break;
+ case O_RANDOM:
+ if (cb->xflags & F_TO_SRC)
info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
- *flags |= IPT_SNAT_OPT_RANDOM;
- } else
- *flags |= IPT_SNAT_OPT_RANDOM;
- return 1;
-
- case '3':
+ break;
+ case O_PERSISTENT:
info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
- return 1;
+ break;
}
- return 0;
-}
-
-static void SNAT_check(unsigned int flags)
-{
- if (!(flags & IPT_SNAT_OPT_SOURCE))
- xtables_error(PARAMETER_PROBLEM,
- "You must specify --to-source");
}
static void print_range(const struct nf_nat_range *r)
@@ -253,11 +244,10 @@ static struct xtables_target snat_tg_reg = {
.size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
.help = SNAT_help,
- .parse = SNAT_parse,
- .final_check = SNAT_check,
+ .x6_parse = SNAT_parse,
.print = SNAT_print,
.save = SNAT_save,
- .extra_opts = SNAT_opts,
+ .x6_options = SNAT_opts,
};
void _init(void)
diff --git a/extensions/libxt_iprange.c b/extensions/libxt_iprange.c
index 2a914165..2c9ea992 100644
--- a/extensions/libxt_iprange.c
+++ b/extensions/libxt_iprange.c
@@ -1,12 +1,7 @@
-/* Shared library add-on to iptables to add IP range matching support. */
-#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
-#include <netdb.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
-
-#include <netinet/in.h>
#include <xtables.h>
#include <linux/netfilter.h>
#include <linux/netfilter/xt_iprange.h>
@@ -25,8 +20,8 @@ struct ipt_iprange_info {
};
enum {
- F_SRCIP = 1 << 0,
- F_DSTIP = 1 << 1,
+ O_SRC_RANGE = 0,
+ O_DST_RANGE,
};
static void iprange_mt_help(void)
@@ -37,10 +32,12 @@ static void iprange_mt_help(void)
"[!] --dst-range ip[-ip] Match destination IP in the specified range\n");
}
-static const struct option iprange_mt_opts[] = {
- {.name = "src-range", .has_arg = true, .val = '1'},
- {.name = "dst-range", .has_arg = true, .val = '2'},
- XT_GETOPT_TABLEEND,
+static const struct xt_option_entry iprange_mt_opts[] = {
+ {.name = "src-range", .id = O_SRC_RANGE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ {.name = "dst-range", .id = O_DST_RANGE, .type = XTTYPE_STRING,
+ .flags = XTOPT_INVERT},
+ XTOPT_TABLEEND,
};
static void
@@ -73,14 +70,18 @@ iprange_parse_spec(const char *from, const char *to, union nf_inet_addr *range,
}
}
-static void iprange_parse_range(char *arg, union nf_inet_addr *range,
+static void iprange_parse_range(const char *oarg, union nf_inet_addr *range,
uint8_t family, const char *optname)
{
+ char *arg = strdup(oarg);
char *dash;
+ if (arg == NULL)
+ xtables_error(RESOURCE_PROBLEM, "strdup");
dash = strchr(arg, '-');
if (dash == NULL) {
iprange_parse_spec(arg, arg, range, family, optname);
+ free(arg);
return;
}
@@ -89,108 +90,71 @@ static void iprange_parse_range(char *arg, union nf_inet_addr *range,
if (memcmp(&range[0], &range[1], sizeof(*range)) > 0)
fprintf(stderr, "xt_iprange: range %s-%s is reversed and "
"will never match\n", arg, dash + 1);
+ free(arg);
}
-static int iprange_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void iprange_parse(struct xt_option_call *cb)
{
- struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
+ struct ipt_iprange_info *info = cb->data;
union nf_inet_addr range[2];
- switch (c) {
- case '1':
- if (*flags & IPRANGE_SRC)
- xtables_error(PARAMETER_PROBLEM,
- "iprange match: Only use --src-range ONCE!");
- *flags |= IPRANGE_SRC;
-
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_RANGE:
info->flags |= IPRANGE_SRC;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- if (invert)
+ if (cb->invert)
info->flags |= IPRANGE_SRC_INV;
- iprange_parse_range(optarg, range, NFPROTO_IPV4, "--src-range");
+ iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--src-range");
info->src.min_ip = range[0].ip;
info->src.max_ip = range[1].ip;
break;
-
- case '2':
- if (*flags & IPRANGE_DST)
- xtables_error(PARAMETER_PROBLEM,
- "iprange match: Only use --dst-range ONCE!");
- *flags |= IPRANGE_DST;
-
+ case O_DST_RANGE:
info->flags |= IPRANGE_DST;
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- if (invert)
+ if (cb->invert)
info->flags |= IPRANGE_DST_INV;
-
- iprange_parse_range(optarg, range, NFPROTO_IPV4, "--dst-range");
+ iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--dst-range");
info->dst.min_ip = range[0].ip;
info->dst.max_ip = range[1].ip;
break;
}
- return 1;
}
-static int
-iprange_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void iprange_mt_parse(struct xt_option_call *cb, uint8_t nfproto)
{
- struct xt_iprange_mtinfo *info = (void *)(*match)->data;
+ struct xt_iprange_mtinfo *info = cb->data;
- switch (c) {
- case '1': /* --src-range */
- iprange_parse_range(optarg, &info->src_min, NFPROTO_IPV4,
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRC_RANGE:
+ iprange_parse_range(cb->arg, &info->src_min, nfproto,
"--src-range");
info->flags |= IPRANGE_SRC;
- if (invert)
+ if (cb->invert)
info->flags |= IPRANGE_SRC_INV;
- *flags |= F_SRCIP;
- return true;
-
- case '2': /* --dst-range */
- iprange_parse_range(optarg, &info->dst_min, NFPROTO_IPV4,
+ break;
+ case O_DST_RANGE:
+ iprange_parse_range(cb->arg, &info->dst_min, nfproto,
"--dst-range");
info->flags |= IPRANGE_DST;
- if (invert)
+ if (cb->invert)
info->flags |= IPRANGE_DST_INV;
- *flags |= F_DSTIP;
- return true;
+ break;
}
- return false;
}
-static int
-iprange_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void iprange_mt4_parse(struct xt_option_call *cb)
{
- struct xt_iprange_mtinfo *info = (void *)(*match)->data;
-
- switch (c) {
- case '1': /* --src-range */
- iprange_parse_range(optarg, &info->src_min, NFPROTO_IPV6,
- "--src-range");
- info->flags |= IPRANGE_SRC;
- if (invert)
- info->flags |= IPRANGE_SRC_INV;
- *flags |= F_SRCIP;
- return true;
+ iprange_mt_parse(cb, NFPROTO_IPV4);
+}
- case '2': /* --dst-range */
- iprange_parse_range(optarg, &info->dst_min, NFPROTO_IPV6,
- "--dst-range");
- info->flags |= IPRANGE_DST;
- if (invert)
- info->flags |= IPRANGE_DST_INV;
- *flags |= F_DSTIP;
- return true;
- }
- return false;
+static void iprange_mt6_parse(struct xt_option_call *cb)
+{
+ iprange_mt_parse(cb, NFPROTO_IPV6);
}
-static void iprange_mt_check(unsigned int flags)
+static void iprange_mt_check(struct xt_fcheck_call *cb)
{
- if (flags == 0)
+ if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"iprange match: You must specify `--src-range' or `--dst-range'");
}
@@ -341,11 +305,11 @@ static struct xtables_match iprange_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
.help = iprange_mt_help,
- .parse = iprange_parse,
- .final_check = iprange_mt_check,
+ .x6_parse = iprange_parse,
+ .x6_fcheck = iprange_mt_check,
.print = iprange_print,
.save = iprange_save,
- .extra_opts = iprange_mt_opts,
+ .x6_options = iprange_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -355,11 +319,11 @@ static struct xtables_match iprange_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
.help = iprange_mt_help,
- .parse = iprange_mt4_parse,
- .final_check = iprange_mt_check,
+ .x6_parse = iprange_mt4_parse,
+ .x6_fcheck = iprange_mt_check,
.print = iprange_mt4_print,
.save = iprange_mt4_save,
- .extra_opts = iprange_mt_opts,
+ .x6_options = iprange_mt_opts,
},
{
.version = XTABLES_VERSION,
@@ -369,11 +333,11 @@ static struct xtables_match iprange_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
.help = iprange_mt_help,
- .parse = iprange_mt6_parse,
- .final_check = iprange_mt_check,
+ .x6_parse = iprange_mt6_parse,
+ .x6_fcheck = iprange_mt_check,
.print = iprange_mt6_print,
.save = iprange_mt6_save,
- .extra_opts = iprange_mt_opts,
+ .x6_options = iprange_mt_opts,
},
};
diff --git a/extensions/libxt_mac.c b/extensions/libxt_mac.c
index d7e65dac..f171d153 100644
--- a/extensions/libxt_mac.c
+++ b/extensions/libxt_mac.c
@@ -1,10 +1,4 @@
-/* Shared library add-on to iptables to add MAC address support. */
-#include <stdbool.h>
#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
#if defined(__GLIBC__) && __GLIBC__ == 2
#include <net/ethernet.h>
#else
@@ -13,6 +7,10 @@
#include <xtables.h>
#include <linux/netfilter/xt_mac.h>
+enum {
+ O_MAC = 0,
+};
+
static void mac_help(void)
{
printf(
@@ -21,70 +19,33 @@ static void mac_help(void)
" Match source MAC address\n");
}
-static const struct option mac_opts[] = {
- {.name = "mac-source", .has_arg = true, .val = '1'},
- XT_GETOPT_TABLEEND,
+#define s struct xt_mac_info
+static const struct xt_option_entry mac_opts[] = {
+ {.name = "mac-source", .id = O_MAC, .type = XTTYPE_ETHERMAC,
+ .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
+ XTOPT_POINTER(s, srcaddr)},
+ XTOPT_TABLEEND,
};
+#undef s
-static void
-parse_mac(const char *mac, struct xt_mac_info *info)
-{
- unsigned int i = 0;
-
- if (strlen(mac) != ETH_ALEN*3-1)
- xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac);
-
- for (i = 0; i < ETH_ALEN; i++) {
- long number;
- char *end;
-
- number = strtol(mac + i*3, &end, 16);
-
- if (end == mac + i*3 + 2
- && number >= 0
- && number <= 255)
- info->srcaddr[i] = number;
- else
- xtables_error(PARAMETER_PROBLEM,
- "Bad mac address `%s'", mac);
- }
-}
-
-static int
-mac_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry, struct xt_entry_match **match)
+static void mac_parse(struct xt_option_call *cb)
{
- struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data;
-
- switch (c) {
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- parse_mac(optarg, macinfo);
- if (invert)
- macinfo->invert = 1;
- *flags = 1;
- break;
- }
+ struct xt_mac_info *macinfo = cb->data;
- return 1;
+ xtables_option_parse(cb);
+ if (cb->invert)
+ macinfo->invert = 1;
}
-static void print_mac(const unsigned char macaddress[ETH_ALEN])
+static void print_mac(const unsigned char *macaddress)
{
unsigned int i;
printf(" %02X", macaddress[0]);
- for (i = 1; i < ETH_ALEN; i++)
+ for (i = 1; i < ETH_ALEN; ++i)
printf(":%02X", macaddress[i]);
}
-static void mac_check(unsigned int flags)
-{
- if (!flags)
- xtables_error(PARAMETER_PROBLEM,
- "You must specify `--mac-source'");
-}
-
static void
mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
@@ -115,11 +76,10 @@ static struct xtables_match mac_match = {
.size = XT_ALIGN(sizeof(struct xt_mac_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mac_info)),
.help = mac_help,
- .parse = mac_parse,
- .final_check = mac_check,
+ .x6_parse = mac_parse,
.print = mac_print,
.save = mac_save,
- .extra_opts = mac_opts,
+ .x6_options = mac_opts,
};
void _init(void)
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 00be61cf..38c0e5ee 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -70,6 +70,7 @@ struct in_addr;
* %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian
* %XTTYPE_PLEN: prefix length
* %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr)
+ * %XTTYPE_ETHERMAC: Ethernet MAC address in hex form
*/
enum xt_option_type {
XTTYPE_NONE,
@@ -95,6 +96,7 @@ enum xt_option_type {
XTTYPE_PORTRC_NE,
XTTYPE_PLEN,
XTTYPE_PLENMASK,
+ XTTYPE_ETHERMAC,
};
/**
@@ -164,6 +166,7 @@ struct xt_option_call {
struct {
uint32_t mark, mask;
};
+ uint8_t ethermac[6];
} val;
/* Wished for a world where the ones below were gone: */
union {
diff --git a/xtoptions.c b/xtoptions.c
index 70370edb..8d54dd8b 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -672,6 +672,30 @@ static void xtopt_parse_hostmask(struct xt_option_call *cb)
cb->arg = orig_arg;
}
+static void xtopt_parse_ethermac(struct xt_option_call *cb)
+{
+ const char *arg = cb->arg;
+ unsigned int i;
+ char *end;
+
+ for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) {
+ cb->val.ethermac[i] = strtoul(arg, &end, 16);
+ if (cb->val.ethermac[i] > UINT8_MAX || *end != ':')
+ goto out;
+ arg = end + 1;
+ }
+ i = ARRAY_SIZE(cb->val.ethermac) - 1;
+ cb->val.ethermac[i] = strtoul(arg, &end, 16);
+ if (cb->val.ethermac[i] > UINT8_MAX || *end != '\0')
+ goto out;
+ if (cb->entry->flags & XTOPT_PUT)
+ memcpy(XTOPT_MKPTR(cb), cb->val.ethermac,
+ sizeof(cb->val.ethermac));
+ return;
+ out:
+ xt_params->exit_err(PARAMETER_PROBLEM, "ether");
+}
+
static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_UINT8] = xtopt_parse_int,
[XTTYPE_UINT16] = xtopt_parse_int,
@@ -695,6 +719,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
[XTTYPE_PORTRC_NE] = xtopt_parse_mport,
[XTTYPE_PLEN] = xtopt_parse_plen,
[XTTYPE_PLENMASK] = xtopt_parse_plenmask,
+ [XTTYPE_ETHERMAC] = xtopt_parse_ethermac,
};
static const size_t xtopt_psize[] = {
@@ -721,6 +746,7 @@ static const size_t xtopt_psize[] = {
[XTTYPE_PORTRC] = sizeof(uint16_t[2]),
[XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]),
[XTTYPE_PLENMASK] = sizeof(union nf_inet_addr),
+ [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]),
};
/**