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.huuskonen@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
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.huuskonen@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