Hi,

I noticed that ipv6 version of ipmask() converter is missing ?

I'm attaching an example implementation for ipv6mask (incomplete:
missing at least documentation / lua) for comments.

Maybe instead of just working with one mask ipv6mask(converter) could
take two arguments: first ipv6mask, second(optional) ipv4 mask applied to
ipv4mapped ipv6 address(::ffff:1.2.3.4).

So something like this:
http-request track-sc0 req.hdr_ip(X,1),ipv6mask(64,24)
X: 1.2.3.4 -> ::ffff:1.2.3.0
X: 2001:dead:beef:bad:c0f:fee:2:1 -> 2001:dead:beef:bad::
({ "ipv6mask", sample_conv_ip6mask, ARG2(1,MSK6,MSK4), NULL, SMP_T_IPV6, 
SMP_T_IPV6 },)
and if the optional second argument is missing then the first mask
is also applied to ipv4mapped address.

I think standard.c/str2mask return status comment doesn't match
implementation (patch 2).

-Jarno

-- 
Jarno Huuskonen
diff --git a/src/arg.c b/src/arg.c
index 52977b7..b31858d 100644
--- a/src/arg.c
+++ b/src/arg.c
@@ -206,8 +206,15 @@ int make_arg_list(const char *in, int len, uint64_t mask, 
struct arg **argp,
                                goto parse_err;
                        break;
 
-               case ARGT_MSK6: /* not yet implemented */
-                       goto not_impl;
+               case ARGT_MSK6:
+                       if (in == beg)    // empty mask
+                               goto empty_err;
+
+                       if (!str2mask6(word, &arg->data.ipv6))
+                               goto parse_err;
+
+                       arg->type = ARGT_IPV6;
+                       break;
 
                case ARGT_TIME:
                        if (in == beg)    // empty time
diff --git a/src/sample.c b/src/sample.c
index 20a59be..3c31f76 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -1562,6 +1562,22 @@ static int sample_conv_ipmask(const struct arg *arg_p, 
struct sample *smp, void
        return 1;
 }
 
+/* takes the ipv6 netmask in arg_p */
+static int sample_conv_ip6mask(const struct arg *arg_p, struct sample *smp, 
void *private)
+{
+       *(uint32_t*)&smp->data.u.ipv6.s6_addr[0] &= 
*(uint32_t*)&arg_p->data.ipv6.s6_addr[0];
+       *(uint32_t*)&smp->data.u.ipv6.s6_addr[4] &= 
*(uint32_t*)&arg_p->data.ipv6.s6_addr[4];
+       *(uint32_t*)&smp->data.u.ipv6.s6_addr[8] &= 
*(uint32_t*)&arg_p->data.ipv6.s6_addr[8];
+       *(uint32_t*)&smp->data.u.ipv6.s6_addr[12] &= 
*(uint32_t*)&arg_p->data.ipv6.s6_addr[12];
+/*     smp->data.u.ipv6.s6_addr32[0] &= arg_p->data.ipv6.s6_addr32[0];
+       smp->data.u.ipv6.s6_addr32[1] &= arg_p->data.ipv6.s6_addr32[1];
+       smp->data.u.ipv6.s6_addr32[2] &= arg_p->data.ipv6.s6_addr32[2];
+       smp->data.u.ipv6.s6_addr32[3] &= arg_p->data.ipv6.s6_addr32[3];
+*/
+       smp->data.type = SMP_T_IPV6;
+       return 1;
+}
+
 /* takes an UINT value on input supposed to represent the time since EPOCH,
  * adds an optional offset found in args[1] and emits a string representing
  * the local time in the format specified in args[1] using strftime().
@@ -2737,6 +2753,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, 
{
        { "lower",  sample_conv_str2lower, 0,            NULL, SMP_T_STR,  
SMP_T_STR  },
        { "hex",    sample_conv_bin2hex,   0,            NULL, SMP_T_BIN,  
SMP_T_STR  },
        { "ipmask", sample_conv_ipmask,    ARG1(1,MSK4), NULL, SMP_T_IPV4, 
SMP_T_IPV4 },
+       { "ipv6mask", sample_conv_ip6mask, ARG1(1,MSK6), NULL, SMP_T_IPV6, 
SMP_T_IPV6 },
        { "ltime",  sample_conv_ltime,     ARG2(1,STR,SINT), NULL, SMP_T_SINT, 
SMP_T_STR },
        { "utime",  sample_conv_utime,     ARG2(1,STR,SINT), NULL, SMP_T_SINT, 
SMP_T_STR },
        { "crc32",  sample_conv_crc32,     ARG1(0,SINT), NULL, SMP_T_BIN,  
SMP_T_SINT  },
diff --git a/src/standard.c b/src/standard.c
index 6abedb4..954abc7 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1029,6 +1029,30 @@ int str2mask(const char *str, struct in_addr *mask)
        return 1;
 }
 
+/* converts <str> to a struct in6_addr containing a network mask. It can be
+ * passed in colon form (ffff:ffff:ffff:ffff::) or in CIDR form (64).
+ * It returns 1 * if the conversion succeeds otherwise zero.
+ */
+int str2mask6(const char *str, struct in6_addr *mask)
+{
+       if (strchr(str, ':') != NULL) {     /* colon notation */
+               if (!inet_pton(AF_INET6, str, mask))
+                       return 0;
+       }
+       else { /* mask length */
+               char *err;
+               unsigned long len = strtol(str, &err, 10);
+
+               if (!*str || (err && *err) || (unsigned)len > 128)
+                       return 0;
+               if (len)
+                       len2mask6(len, mask);
+               else
+                       memset(mask, 0, sizeof(*mask));
+       }
+       return 1;
+}
+
 /* convert <cidr> to struct in_addr <mask>. It returns 1 if the conversion
  * succeeds otherwise zero.
  */
>From d78ede55949e00f6bb87decd529655f459703610 Mon Sep 17 00:00:00 2001
From: Jarno Huuskonen <jarno.huusko...@uef.fi>
Date: Sun, 21 May 2017 17:32:21 +0300
Subject: [PATCH] CLEANUP: str2mask return code comment: non-zero -> zero.

---
 include/common/standard.h | 2 +-
 src/standard.c            | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/common/standard.h b/include/common/standard.h
index 4ba6a95..7de8ead 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -371,7 +371,7 @@ struct sockaddr_storage *str2sa_range(const char *str,
 
 /* converts <str> to a struct in_addr containing a network mask. It can be
  * passed in dotted form (255.255.255.0) or in CIDR form (24). It returns 1
- * if the conversion succeeds otherwise non-zero.
+ * if the conversion succeeds otherwise zero.
  */
 int str2mask(const char *str, struct in_addr *mask);
 
diff --git a/src/standard.c b/src/standard.c
index 6abedb4..95d83e4 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1007,7 +1007,7 @@ struct sockaddr_storage *str2sa_range(const char *str, 
int *port, int *low, int
 
 /* converts <str> to a struct in_addr containing a network mask. It can be
  * passed in dotted form (255.255.255.0) or in CIDR form (24). It returns 1
- * if the conversion succeeds otherwise non-zero.
+ * if the conversion succeeds otherwise zero.
  */
 int str2mask(const char *str, struct in_addr *mask)
 {
-- 
1.8.3.1

Reply via email to