]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
libxtables: XTTYPE_ONEHOST support
authorJan Engelhardt <jengelh@medozas.de>
Mon, 14 Feb 2011 14:10:15 +0000 (15:10 +0100)
committerJan Engelhardt <jengelh@medozas.de>
Wed, 13 Apr 2011 16:09:27 +0000 (18:09 +0200)
The bonus of the POSIX socket API is that it is almost protocol-agnostic
and that there are ready-made functions to take over the gist of address
parsing and packing.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
include/xtables.h.in
xtoptions.c

index afdac36a6f449300f7d2db8af56e75063cfd3868..d8a31245803bfed61028094469c1f312fd4fb20e 100644 (file)
@@ -52,6 +52,7 @@ struct in_addr;
  * %XTTYPE_STRING:     arbitrary string
  * %XTTYPE_MARKMASK32: 32-bit mark with optional mask
  * %XTTYPE_SYSLOGLEVEL:        syslog level by name or number
+ * %XTTYPE_ONEHOST:    one host or address (union nf_inet_addr)
  */
 enum xt_option_type {
        XTTYPE_NONE,
@@ -66,6 +67,7 @@ enum xt_option_type {
        XTTYPE_STRING,
        XTTYPE_MARKMASK32,
        XTTYPE_SYSLOGLEVEL,
+       XTTYPE_ONEHOST,
 };
 
 /**
@@ -124,6 +126,7 @@ struct xt_option_call {
                uint16_t u16, u16_range[2];
                uint32_t u32, u32_range[2];
                uint64_t u64, u64_range[2];
+               union nf_inet_addr inetaddr;
                struct {
                        uint32_t mark, mask;
                };
index a6738c11ea22340a55ef4736b1cdcd72caef1636..e0c3213f30aeec40a82d9c1aa0c67b015c547cb9 100644 (file)
@@ -297,6 +297,63 @@ static void xtopt_parse_sysloglevel(struct xt_option_call *cb)
                *(uint8_t *)XTOPT_MKPTR(cb) = num;
 }
 
+static void *xtables_sa_host(const void *sa, unsigned int afproto)
+{
+       if (afproto == AF_INET6)
+               return &((struct sockaddr_in6 *)sa)->sin6_addr;
+       else if (afproto == AF_INET)
+               return &((struct sockaddr_in *)sa)->sin_addr;
+       return (void *)sa;
+}
+
+static socklen_t xtables_sa_hostlen(unsigned int afproto)
+{
+       if (afproto == AF_INET6)
+               return sizeof(struct in6_addr);
+       else if (afproto == AF_INET)
+               return sizeof(struct in_addr);
+       return 0;
+}
+
+/**
+ * Accepts: a hostname (DNS), or a single inetaddr.
+ */
+static void xtopt_parse_onehost(struct xt_option_call *cb)
+{
+       struct addrinfo hints = {.ai_family = afinfo->family};
+       unsigned int adcount = 0;
+       struct addrinfo *res, *p;
+       int ret;
+
+       ret = getaddrinfo(cb->arg, NULL, &hints, &res);
+       if (ret < 0)
+               xt_params->exit_err(PARAMETER_PROBLEM,
+                       "getaddrinfo: %s\n", gai_strerror(ret));
+
+       for (p = res; p != NULL; p = p->ai_next) {
+               if (adcount == 0) {
+                       memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr));
+                       memcpy(&cb->val.inetaddr,
+                              xtables_sa_host(p->ai_addr, p->ai_family),
+                              xtables_sa_hostlen(p->ai_family));
+                       ++adcount;
+                       continue;
+               }
+               if (memcmp(&cb->val.inetaddr,
+                   xtables_sa_host(p->ai_addr, p->ai_family),
+                   xtables_sa_hostlen(p->ai_family)) != 0)
+                       xt_params->exit_err(PARAMETER_PROBLEM,
+                               "%s resolves to more than one address\n",
+                               cb->arg);
+       }
+
+       freeaddrinfo(res);
+       if (cb->entry->flags & XTOPT_PUT)
+               /* Validation in xtables_option_metavalidate */
+               memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr,
+                      sizeof(cb->val.inetaddr));
+}
+
 static void (*const xtopt_subparse[])(struct xt_option_call *) = {
        [XTTYPE_UINT8]       = xtopt_parse_int,
        [XTTYPE_UINT16]      = xtopt_parse_int,
@@ -309,6 +366,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = {
        [XTTYPE_STRING]      = xtopt_parse_string,
        [XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
        [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
+       [XTTYPE_ONEHOST]     = xtopt_parse_onehost,
 };
 
 static const size_t xtopt_psize[] = {
@@ -322,6 +380,7 @@ static const size_t xtopt_psize[] = {
        [XTTYPE_UINT64RC]    = sizeof(uint64_t[2]),
        [XTTYPE_STRING]      = -1,
        [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
+       [XTTYPE_ONEHOST]     = sizeof(union nf_inet_addr),
 };
 
 /**