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); ...@@ -42,6 +42,7 @@ int mu_cidr_from_sockaddr (struct mu_cidr *cp, const struct sockaddr *sa);
42 int mu_cidr_from_string (struct mu_cidr *cp, const char *str); 42 int mu_cidr_from_string (struct mu_cidr *cp, const char *str);
43 43
44 #define MU_CIDR_FMT_ADDRONLY 0x01 44 #define MU_CIDR_FMT_ADDRONLY 0x01
45 #define MU_CIDR_FMT_SIMPLIFY 0x02
45 46
46 int mu_cidr_to_string (struct mu_cidr *cidr, int flags, char *buf, size_t size, 47 int mu_cidr_to_string (struct mu_cidr *cidr, int flags, char *buf, size_t size,
47 size_t *pret); 48 size_t *pret);
......
...@@ -34,33 +34,102 @@ to_xdig (unsigned char b) ...@@ -34,33 +34,102 @@ to_xdig (unsigned char b)
34 34
35 static size_t 35 static size_t
36 format_ipv6_bytes (const unsigned char *bytes, int len, 36 format_ipv6_bytes (const unsigned char *bytes, int len,
37 char *buf, size_t size) 37 char *buf, size_t size, int simplify)
38 { 38 {
39 size_t total = 0; 39 size_t total = 0;
40 int i; 40 int i;
41 int run_count = 0;
42 char *p;
41 43
42 for (i = 0; i < len; i += 2) 44 for (i = 0; i < len; i += 2)
43 { 45 {
44 if (i) 46 if (bytes[0] == 0 && bytes[1] == 0)
47 {
48 if (simplify)
49 run_count++;
50 else
51 {
52 if (i && total++ < size)
53 *buf++ = ':';
54 if (total++ < size)
55 *buf++ = '0';
56 }
57 bytes += 2;
58 }
59 else
60 {
61 if (run_count)
62 {
63 if (run_count == 1)
64 {
65 if (i && total++ < size)
66 *buf++ = ':';
67 if (total++ < size)
68 *buf++ = '0';
69 }
70 else
71 {
72 if (total++ < size)
73 *buf++ = ':';
74 simplify = 0;
75 }
76 run_count = 0;
77 }
78
79 if (i && total++ < size)
80 *buf++ = ':';
81
82 p = buf;
83 if ((*bytes & 0xf0) && total++ < size)
84 *buf++ = to_xdig (*bytes >> 4);
85 if ((buf > p || (*bytes & 0xf)) && total++ < size)
86 *buf++ = to_xdig (*bytes & 0xf);
87 bytes++;
88 if ((buf > p || (*bytes & 0xf0)) && total++ < size)
89 *buf++ = to_xdig (*bytes >> 4);
90 if ((buf > p || (*bytes & 0xf)) && total++ < size)
91 *buf++ = to_xdig (*bytes & 0xf);
92 bytes++;
93 }
94 }
95
96 if (run_count)
97 {
98 if (run_count == 1)
99 {
100 if (i && total++ < size)
101 *buf++ = ':';
102 if (total++ < size)
103 *buf++ = '0';
104 }
105 else
45 { 106 {
46 if (total++ < size) 107 if (total++ < size)
47 *buf++ = ':'; 108 *buf++ = ':';
109 if (total++ < size)
110 *buf++ = ':';
48 } 111 }
49 if (total++ < size)
50 *buf++ = to_xdig (*bytes >> 4);
51 if (total++ < size)
52 *buf++ = to_xdig (*bytes & 0xf);
53 bytes++;
54 if (total++ < size)
55 *buf++ = to_xdig (*bytes >> 4);
56 if (total++ < size)
57 *buf++ = to_xdig (*bytes & 0xf);
58 bytes++;
59 } 112 }
113
60 return total; 114 return total;
61 } 115 }
62 116
63 static size_t 117 static size_t
118 format_ipv6_bytes_normal (const unsigned char *bytes, int len,
119 char *buf, size_t size)
120 {
121 return format_ipv6_bytes (bytes, len, buf, size, 0);
122 }
123
124 static size_t
125 format_ipv6_bytes_simplified (const unsigned char *bytes, int len,
126 char *buf, size_t size)
127 {
128 return format_ipv6_bytes (bytes, len, buf, size, 1);
129 }
130
131
132 static size_t
64 format_ipv4_bytes (const unsigned char *bytes, int len, 133 format_ipv4_bytes (const unsigned char *bytes, int len,
65 char *buf, size_t size) 134 char *buf, size_t size)
66 { 135 {
...@@ -114,7 +183,8 @@ mu_cidr_to_string (struct mu_cidr *cidr, int flags, ...@@ -114,7 +183,8 @@ mu_cidr_to_string (struct mu_cidr *cidr, int flags,
114 183
115 #ifdef MAILUTILS_IPV6 184 #ifdef MAILUTILS_IPV6
116 case AF_INET6: 185 case AF_INET6:
117 fmt = format_ipv6_bytes; 186 fmt = (flags & MU_CIDR_FMT_SIMPLIFY) ?
187 format_ipv6_bytes_simplified : format_ipv6_bytes_normal;
118 break; 188 break;
119 #endif 189 #endif
120 190
......
...@@ -33,10 +33,12 @@ print_bytes (unsigned char *b, size_t l) ...@@ -33,10 +33,12 @@ print_bytes (unsigned char *b, size_t l)
33 int 33 int
34 main (int argc, char **argv) 34 main (int argc, char **argv)
35 { 35 {
36 int flags = 0;
37
36 mu_set_program_name (argv[0]); 38 mu_set_program_name (argv[0]);
37 if (argc < 2) 39 if (argc < 2)
38 { 40 {
39 mu_error ("usage: %s CIDR [CIDR...]", argv[0]); 41 mu_error ("usage: %s [-sS] CIDR [CIDR...]", argv[0]);
40 return 1; 42 return 1;
41 } 43 }
42 44
...@@ -46,7 +48,18 @@ main (int argc, char **argv) ...@@ -46,7 +48,18 @@ main (int argc, char **argv)
46 struct mu_cidr cidr; 48 struct mu_cidr cidr;
47 int rc; 49 int rc;
48 char *str; 50 char *str;
49 51
52 if (strcmp (arg, "-s") == 0)
53 {
54 flags |= MU_CIDR_FMT_SIMPLIFY;
55 continue;
56 }
57 else if (strcmp (arg, "-S") == 0)
58 {
59 flags &= ~MU_CIDR_FMT_SIMPLIFY;
60 continue;
61 }
62
50 rc = mu_cidr_from_string (&cidr, arg); 63 rc = mu_cidr_from_string (&cidr, arg);
51 if (rc) 64 if (rc)
52 { 65 {
...@@ -61,7 +74,7 @@ main (int argc, char **argv) ...@@ -61,7 +74,7 @@ main (int argc, char **argv)
61 print_bytes (cidr.address, cidr.len); 74 print_bytes (cidr.address, cidr.len);
62 printf ("netmask ="); 75 printf ("netmask =");
63 print_bytes (cidr.netmask, cidr.len); 76 print_bytes (cidr.netmask, cidr.len);
64 rc = mu_cidr_format (&cidr, 0, &str); 77 rc = mu_cidr_format (&cidr, flags, &str);
65 if (rc) 78 if (rc)
66 { 79 {
67 mu_error ("cannot covert to string: %s", mu_strerror (rc)); 80 mu_error ("cannot covert to string: %s", mu_strerror (rc));
......