summaryrefslogtreecommitdiffstats
path: root/xtables.c
diff options
context:
space:
mode:
Diffstat (limited to 'xtables.c')
-rw-r--r--xtables.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/xtables.c b/xtables.c
index e0183310..41e0b871 100644
--- a/xtables.c
+++ b/xtables.c
@@ -271,6 +271,18 @@ void *xtables_malloc(size_t size)
return p;
}
+void *xtables_realloc(void *ptr, size_t size)
+{
+ void *p;
+
+ if ((p = realloc(ptr, size)) == NULL) {
+ perror("ip[6]tables: realloc failed");
+ exit(1);
+ }
+
+ return p;
+}
+
static char *get_modprobe(void)
{
int procfile;
@@ -712,6 +724,11 @@ void xtables_register_match(struct xtables_match *me)
{
struct xtables_match **i, *old;
+ if (me->version == NULL) {
+ fprintf(stderr, "%s: match %s<%u> is missing a version\n",
+ xt_params->program_name, me->name, me->revision);
+ exit(1);
+ }
if (strcmp(me->version, XTABLES_VERSION) != 0) {
fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
"but \"%s\" is required.\n",
@@ -782,10 +799,22 @@ void xtables_register_match(struct xtables_match *me)
me->mflags = 0;
}
+void xtables_register_matches(struct xtables_match *match, unsigned int n)
+{
+ do {
+ xtables_register_match(&match[--n]);
+ } while (n > 0);
+}
+
void xtables_register_target(struct xtables_target *me)
{
struct xtables_target *old;
+ if (me->version == NULL) {
+ fprintf(stderr, "%s: target %s<%u> is missing a version\n",
+ xt_params->program_name, me->name, me->revision);
+ exit(1);
+ }
if (strcmp(me->version, XTABLES_VERSION) != 0) {
fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
"but \"%s\" is required.\n",
@@ -856,6 +885,13 @@ void xtables_register_target(struct xtables_target *me)
me->tflags = 0;
}
+void xtables_register_targets(struct xtables_target *target, unsigned int n)
+{
+ do {
+ xtables_register_target(&target[--n]);
+ } while (n > 0);
+}
+
/**
* xtables_param_act - act on condition
* @status: a constant from enum xtables_exittype
@@ -1133,6 +1169,86 @@ static struct in_addr *parse_ipmask(const char *mask)
return &maskaddr;
}
+void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
+ struct in_addr **maskpp, unsigned int *naddrs)
+{
+ struct in_addr *addrp;
+ char buf[256], *p;
+ unsigned int len, i, j, n, count = 1;
+ const char *loop = name;
+
+ while ((loop = strchr(loop, ',')) != NULL) {
+ ++count;
+ ++loop; /* skip ',' */
+ }
+
+ *addrpp = xtables_malloc(sizeof(struct in_addr) * count);
+ *maskpp = xtables_malloc(sizeof(struct in_addr) * count);
+
+ loop = name;
+
+ for (i = 0; i < count; ++i) {
+ if (loop == NULL)
+ break;
+ if (*loop == ',')
+ ++loop;
+ if (*loop == '\0')
+ break;
+ p = strchr(loop, ',');
+ if (p != NULL)
+ len = p - loop;
+ else
+ len = strlen(loop);
+ if (len == 0 || sizeof(buf) - 1 < len)
+ break;
+
+ strncpy(buf, loop, len);
+ buf[len] = '\0';
+ loop += len;
+ if ((p = strrchr(buf, '/')) != NULL) {
+ *p = '\0';
+ addrp = parse_ipmask(p + 1);
+ } else {
+ addrp = parse_ipmask(NULL);
+ }
+ memcpy(*maskpp + i, addrp, sizeof(*addrp));
+
+ /* if a null mask is given, the name is ignored, like in "any/0" */
+ if ((*maskpp + i)->s_addr == 0)
+ /*
+ * A bit pointless to process multiple addresses
+ * in this case...
+ */
+ strcpy(buf, "0.0.0.0");
+
+ addrp = ipparse_hostnetwork(buf, &n);
+ if (n > 1) {
+ count += n - 1;
+ *addrpp = xtables_realloc(*addrpp,
+ sizeof(struct in_addr) * count);
+ *maskpp = xtables_realloc(*maskpp,
+ sizeof(struct in_addr) * count);
+ for (j = 0; j < n; ++j)
+ /* for each new addr */
+ memcpy(*addrpp + i + j, addrp + j,
+ sizeof(*addrp));
+ for (j = 1; j < n; ++j)
+ /* for each new mask */
+ memcpy(*maskpp + i + j, *maskpp + i,
+ sizeof(*addrp));
+ i += n - 1;
+ } else {
+ memcpy(*addrpp + i, addrp, sizeof(*addrp));
+ }
+ /* free what ipparse_hostnetwork had allocated: */
+ free(addrp);
+ }
+ *naddrs = count;
+ for (i = 0; i < n; ++i)
+ (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
+}
+
+
/**
* xtables_ipparse_any - transform arbitrary name to in_addr
*
@@ -1364,6 +1480,89 @@ static struct in6_addr *parse_ip6mask(char *mask)
return &maskaddr;
}
+void
+xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
+ struct in6_addr **maskpp, unsigned int *naddrs)
+{
+ struct in6_addr *addrp;
+ char buf[256], *p;
+ unsigned int len, i, j, n, count = 1;
+ const char *loop = name;
+
+ while ((loop = strchr(loop, ',')) != NULL) {
+ ++count;
+ ++loop; /* skip ',' */
+ }
+
+ *addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
+ *maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
+
+ loop = name;
+
+ for (i = 0; i < count /*NB: count can grow*/; ++i) {
+ if (loop == NULL)
+ break;
+ if (*loop == ',')
+ ++loop;
+ if (*loop == '\0')
+ break;
+ p = strchr(loop, ',');
+ if (p != NULL)
+ len = p - loop;
+ else
+ len = strlen(loop);
+ if (len == 0 || sizeof(buf) - 1 < len)
+ break;
+
+ strncpy(buf, loop, len);
+ buf[len] = '\0';
+ loop += len;
+ if ((p = strrchr(buf, '/')) != NULL) {
+ *p = '\0';
+ addrp = parse_ip6mask(p + 1);
+ } else {
+ addrp = parse_ip6mask(NULL);
+ }
+ memcpy(*maskpp + i, addrp, sizeof(*addrp));
+
+ /* if a null mask is given, the name is ignored, like in "any/0" */
+ if (memcmp(*maskpp + i, &in6addr_any, sizeof(in6addr_any)) == 0)
+ strcpy(buf, "::");
+
+ addrp = ip6parse_hostnetwork(buf, &n);
+ /* ip6parse_hostnetwork only ever returns one IP
+ address (it exits if the resolution fails).
+ Therefore, n will always be 1 here. Leaving the
+ code below in anyway in case ip6parse_hostnetwork
+ is improved some day to behave like
+ ipparse_hostnetwork: */
+ if (n > 1) {
+ count += n - 1;
+ *addrpp = xtables_realloc(*addrpp,
+ sizeof(struct in6_addr) * count);
+ *maskpp = xtables_realloc(*maskpp,
+ sizeof(struct in6_addr) * count);
+ for (j = 0; j < n; ++j)
+ /* for each new addr */
+ memcpy(*addrpp + i + j, addrp + j,
+ sizeof(*addrp));
+ for (j = 1; j < n; ++j)
+ /* for each new mask */
+ memcpy(*maskpp + i + j, *maskpp + i,
+ sizeof(*addrp));
+ i += n - 1;
+ } else {
+ memcpy(*addrpp + i, addrp, sizeof(*addrp));
+ }
+ /* free what ip6parse_hostnetwork had allocated: */
+ free(addrp);
+ }
+ *naddrs = count;
+ for (i = 0; i < n; ++i)
+ for (j = 0; j < 4; ++j)
+ (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
+}
+
void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
struct in6_addr *maskp, unsigned int *naddrs)
{