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