Commit dd07fe07 dd07fe07ac35257c75d0f9fb3b8dd02387182a1b by Sergey Poznyakoff

cidr: Implement simplified IPv6 formats

* include/mailutils/cidr.h (MU_CIDR_FMT_SIMPLIFY): New format flag.
* libmailutils/cidr/tostr.c (format_ipv6_bytes): Take additional
argument, indicating whether to simplify the output.
(format_ipv6_bytes_normal)
(format_ipv6_bytes_simplified): New static functions.
(mu_cidr_to_string): Select appropriate ipv6 printer depending on
the MU_CIDR_FMT_SIMPLIFY bit.
* libmailutils/tests/cidr.c (main): New options -s and -S
1 parent c1a08f80
......@@ -42,6 +42,7 @@ int mu_cidr_from_sockaddr (struct mu_cidr *cp, const struct sockaddr *sa);
int mu_cidr_from_string (struct mu_cidr *cp, const char *str);
#define MU_CIDR_FMT_ADDRONLY 0x01
#define MU_CIDR_FMT_SIMPLIFY 0x02
int mu_cidr_to_string (struct mu_cidr *cidr, int flags, char *buf, size_t size,
size_t *pret);
......
......@@ -34,33 +34,102 @@ to_xdig (unsigned char b)
static size_t
format_ipv6_bytes (const unsigned char *bytes, int len,
char *buf, size_t size)
char *buf, size_t size, int simplify)
{
size_t total = 0;
int i;
int run_count = 0;
char *p;
for (i = 0; i < len; i += 2)
{
if (i)
if (bytes[0] == 0 && bytes[1] == 0)
{
if (simplify)
run_count++;
else
{
if (i && total++ < size)
*buf++ = ':';
if (total++ < size)
*buf++ = '0';
}
bytes += 2;
}
else
{
if (run_count)
{
if (run_count == 1)
{
if (i && total++ < size)
*buf++ = ':';
if (total++ < size)
*buf++ = '0';
}
else
{
if (total++ < size)
*buf++ = ':';
simplify = 0;
}
run_count = 0;
}
if (i && total++ < size)
*buf++ = ':';
p = buf;
if ((*bytes & 0xf0) && total++ < size)
*buf++ = to_xdig (*bytes >> 4);
if ((buf > p || (*bytes & 0xf)) && total++ < size)
*buf++ = to_xdig (*bytes & 0xf);
bytes++;
if ((buf > p || (*bytes & 0xf0)) && total++ < size)
*buf++ = to_xdig (*bytes >> 4);
if ((buf > p || (*bytes & 0xf)) && total++ < size)
*buf++ = to_xdig (*bytes & 0xf);
bytes++;
}
}
if (run_count)
{
if (run_count == 1)
{
if (i && total++ < size)
*buf++ = ':';
if (total++ < size)
*buf++ = '0';
}
else
{
if (total++ < size)
*buf++ = ':';
if (total++ < size)
*buf++ = ':';
}
if (total++ < size)
*buf++ = to_xdig (*bytes >> 4);
if (total++ < size)
*buf++ = to_xdig (*bytes & 0xf);
bytes++;
if (total++ < size)
*buf++ = to_xdig (*bytes >> 4);
if (total++ < size)
*buf++ = to_xdig (*bytes & 0xf);
bytes++;
}
return total;
}
static size_t
format_ipv6_bytes_normal (const unsigned char *bytes, int len,
char *buf, size_t size)
{
return format_ipv6_bytes (bytes, len, buf, size, 0);
}
static size_t
format_ipv6_bytes_simplified (const unsigned char *bytes, int len,
char *buf, size_t size)
{
return format_ipv6_bytes (bytes, len, buf, size, 1);
}
static size_t
format_ipv4_bytes (const unsigned char *bytes, int len,
char *buf, size_t size)
{
......@@ -114,7 +183,8 @@ mu_cidr_to_string (struct mu_cidr *cidr, int flags,
#ifdef MAILUTILS_IPV6
case AF_INET6:
fmt = format_ipv6_bytes;
fmt = (flags & MU_CIDR_FMT_SIMPLIFY) ?
format_ipv6_bytes_simplified : format_ipv6_bytes_normal;
break;
#endif
......
......@@ -33,10 +33,12 @@ print_bytes (unsigned char *b, size_t l)
int
main (int argc, char **argv)
{
int flags = 0;
mu_set_program_name (argv[0]);
if (argc < 2)
{
mu_error ("usage: %s CIDR [CIDR...]", argv[0]);
mu_error ("usage: %s [-sS] CIDR [CIDR...]", argv[0]);
return 1;
}
......@@ -46,7 +48,18 @@ main (int argc, char **argv)
struct mu_cidr cidr;
int rc;
char *str;
if (strcmp (arg, "-s") == 0)
{
flags |= MU_CIDR_FMT_SIMPLIFY;
continue;
}
else if (strcmp (arg, "-S") == 0)
{
flags &= ~MU_CIDR_FMT_SIMPLIFY;
continue;
}
rc = mu_cidr_from_string (&cidr, arg);
if (rc)
{
......@@ -61,7 +74,7 @@ main (int argc, char **argv)
print_bytes (cidr.address, cidr.len);
printf ("netmask =");
print_bytes (cidr.netmask, cidr.len);
rc = mu_cidr_format (&cidr, 0, &str);
rc = mu_cidr_format (&cidr, flags, &str);
if (rc)
{
mu_error ("cannot covert to string: %s", mu_strerror (rc));
......