* [PATCH 1/2] util: add util_ip_prefix_tohl
@ 2020-10-26 20:35 James Prestwood
2020-10-26 20:35 ` [PATCH 2/2] unit: add test for util_ip_prefix_tohl James Prestwood
2020-10-26 21:17 ` [PATCH 1/2] util: add util_ip_prefix_tohl Denis Kenzior
0 siblings, 2 replies; 3+ messages in thread
From: James Prestwood @ 2020-10-26 20:35 UTC (permalink / raw)
To: iwd
[-- Attachment #1: Type: text/plain, Size: 3292 bytes --]
Parses an IP prefix notation string into prefix, start, end, and
netmask. All values are returned in host order.
---
src/util.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/util.h | 3 ++
2 files changed, 93 insertions(+)
- Moved these two into their own set
- Changed the loop to only iterate over the maximum IP string size (16).
This prevents looping through a really long (invalid) IP string
- Use l_strlcpy instead of memcpy + NULL terminate
diff --git a/src/util.c b/src/util.c
index 13b01c81..ac22b261 100644
--- a/src/util.c
+++ b/src/util.c
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <sys/uio.h>
#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <ell/ell.h>
@@ -218,3 +220,91 @@ const char *util_get_username(const char *identity)
return identity;
}
+
+static bool is_prefix_valid(uint32_t ip, unsigned int prefix)
+{
+ int i;
+
+ for (i = 31 - prefix; i >= 0; i--) {
+ if (ip & (1 << i))
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Parse a prefix notation IP string (e.g. A.B.C.D/E) into an IP range and
+ * netmask. All returned IP addresses/mask will be in host order. The start/end
+ * IP will only include the usable IP range where the last octet is not zero or
+ * 255.
+ */
+bool util_ip_prefix_tohl(const char *ip, uint8_t *prefix_out,
+ uint32_t *start_out, uint32_t *end_out,
+ uint32_t *mask_out)
+{
+ struct in_addr ia;
+ int i;
+ unsigned int prefix = 0;
+ char no_prefix[INET_ADDRSTRLEN];
+ char *endp;
+ uint32_t start_ip;
+ uint32_t end_ip;
+ uint32_t netmask = 0xffffffff;
+
+ /*
+ * Only iterate over the max length of an IP in case of invalid long
+ * inputs.
+ */
+ for (i = 0; i < INET_ADDRSTRLEN && ip[i] != '\0'; i++) {
+ /* Found '/', check the next byte exists and parse prefix */
+ if (ip[i] == '/' && ip[i + 1] != '\0') {
+ prefix = strtol(ip + i + 1, &endp, 10);
+ if (*endp != '\0')
+ return false;
+
+ break;
+ }
+ }
+
+ if (prefix < 1 || prefix > 31)
+ return false;
+
+ /* 'i' will be at most INET_ADDRSTRLEN - 1 */
+ l_strlcpy(no_prefix, ip, i + 1);
+
+ /* Check if IP preceeding prefix is valid */
+ if (inet_pton(AF_INET, no_prefix, &ia) != 1 || ia.s_addr == 0)
+ return false;
+
+ start_ip = ntohl(ia.s_addr);
+
+ if (!is_prefix_valid(start_ip, prefix))
+ return false;
+
+ /* Usable range is start + 1 .. end - 1 */
+ start_ip += 1;
+
+ /* Calculate end IP and netmask */
+ end_ip = start_ip;
+ for (i = 31 - prefix; i >= 0; i--) {
+ end_ip |= (1 << i);
+ netmask &= ~(1 << i);
+ }
+
+ end_ip -= 1;
+
+ if (prefix_out)
+ *prefix_out = prefix;
+
+ if (start_out)
+ *start_out = start_ip;
+
+ if (end_out)
+ *end_out = end_ip;
+
+ if (mask_out)
+ *mask_out = netmask;
+
+ return true;
+}
diff --git a/src/util.h b/src/util.h
index 2679c117..e6b4747f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -107,4 +107,7 @@ static inline uint32_t util_secure_fill_with_msb(uint32_t val)
return (uint32_t) (val >> (sizeof(val)*8 - 1)) * 0xFFFFFFFF;
}
+bool util_ip_prefix_tohl(const char *ip, uint8_t *prefix, uint32_t *start_out,
+ uint32_t *end_out, uint32_t *mask_out);
+
#endif /* __UTIL_H */
--
2.26.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] unit: add test for util_ip_prefix_tohl
2020-10-26 20:35 [PATCH 1/2] util: add util_ip_prefix_tohl James Prestwood
@ 2020-10-26 20:35 ` James Prestwood
2020-10-26 21:17 ` [PATCH 1/2] util: add util_ip_prefix_tohl Denis Kenzior
1 sibling, 0 replies; 3+ messages in thread
From: James Prestwood @ 2020-10-26 20:35 UTC (permalink / raw)
To: iwd
[-- Attachment #1: Type: text/plain, Size: 2878 bytes --]
---
unit/test-util.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
- Added a very long invalid IP string test
- Added a valid IP string that is maximum length possible
diff --git a/unit/test-util.c b/unit/test-util.c
index f091f2c2..c3f8c673 100644
--- a/unit/test-util.c
+++ b/unit/test-util.c
@@ -27,6 +27,8 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <ell/ell.h>
#include "src/util.h"
@@ -115,6 +117,68 @@ static void get_username_test(const void *data)
assert(strcmp(test, "username") == 0);
}
+static void ip_prefix_test(const void *data)
+{
+ unsigned int i;
+ char *invalid[] = {
+ "192.168.0.0", /* Not prefix notation */
+ "192.168./22", /* Incomplete notation */
+ "192.168.0.1/255", /* Too long prefix */
+ "192.168.0.1/0", /* Too short prefix */
+ "192.168.0.1/16", /* Invalid prefix */
+ "192.168.1.2.3/24", /* IP too long */
+ "192.168.111.222.333.444/20", /* IP way too long */
+ };
+
+ struct {
+ char *ip_prefix;
+ uint8_t prefix;
+ char *start;
+ char *end;
+ char *mask;
+ } valid[] = {
+ {"192.168.80.0/22", 22, "192.168.80.1",
+ "192.168.83.254", "255.255.252.0"},
+ {"192.168.128.0/20", 20, "192.168.128.1",
+ "192.168.143.254", "255.255.240.0"},
+ {"192.168.0.0/25", 25, "192.168.0.1",
+ "192.168.0.126", "255.255.255.128"},
+ {"192.168.0.0/29", 29, "192.168.0.1",
+ "192.168.0.6", "255.255.255.248"},
+ {"192.168.0.128/25", 25, "192.168.0.129",
+ "192.168.0.254", "255.255.255.128"},
+ /* Valid notation which is maximum length */
+ {"192.168.111.108/30", 30, "192.168.111.109",
+ "192.168.111.110", "255.255.255.252"},
+ };
+
+ for (i = 0; i < L_ARRAY_SIZE(invalid); i++)
+ assert(!util_ip_prefix_tohl(invalid[i], NULL, NULL,
+ NULL, NULL));
+
+ for (i = 0; i < L_ARRAY_SIZE(valid); i++) {
+ uint8_t prefix;
+ uint32_t start;
+ uint32_t end;
+ uint32_t mask;
+ struct in_addr ia;
+
+ assert(util_ip_prefix_tohl(valid[i].ip_prefix,
+ &prefix, &start, &end, &mask));
+
+ assert(valid[i].prefix == prefix);
+
+ ia.s_addr = htonl(start);
+ assert(strcmp(inet_ntoa(ia), valid[i].start) == 0);
+
+ ia.s_addr = htonl(end);
+ assert(strcmp(inet_ntoa(ia), valid[i].end) == 0);
+
+ ia.s_addr = htonl(mask);
+ assert(strcmp(inet_ntoa(ia), valid[i].mask) == 0);
+ }
+}
+
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@@ -122,6 +186,7 @@ int main(int argc, char *argv[])
l_test_add("/util/ssid_to_utf8/", ssid_to_utf8, ssid_samples);
l_test_add("/util/get_domain/", get_domain_test, NULL);
l_test_add("/util/get_username/", get_username_test, NULL);
+ l_test_add("/util/ip_prefix/", ip_prefix_test, NULL);
return l_test_run();
}
--
2.26.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] util: add util_ip_prefix_tohl
2020-10-26 20:35 [PATCH 1/2] util: add util_ip_prefix_tohl James Prestwood
2020-10-26 20:35 ` [PATCH 2/2] unit: add test for util_ip_prefix_tohl James Prestwood
@ 2020-10-26 21:17 ` Denis Kenzior
1 sibling, 0 replies; 3+ messages in thread
From: Denis Kenzior @ 2020-10-26 21:17 UTC (permalink / raw)
To: iwd
[-- Attachment #1: Type: text/plain, Size: 1060 bytes --]
Hi James,
On 10/26/20 3:35 PM, James Prestwood wrote:
> Parses an IP prefix notation string into prefix, start, end, and
> netmask. All values are returned in host order.
> ---
> src/util.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/util.h | 3 ++
> 2 files changed, 93 insertions(+)
>
> - Moved these two into their own set
> - Changed the loop to only iterate over the maximum IP string size (16).
> This prevents looping through a really long (invalid) IP string
> - Use l_strlcpy instead of memcpy + NULL terminate
<snip>
> + /*
> + * Only iterate over the max length of an IP in case of invalid long
> + * inputs.
> + */
> + for (i = 0; i < INET_ADDRSTRLEN && ip[i] != '\0'; i++) {
> + /* Found '/', check the next byte exists and parse prefix */
> + if (ip[i] == '/' && ip[i + 1] != '\0') {
> + prefix = strtol(ip + i + 1, &endp, 10);
I changed this to strtoul and..
> + if (*endp != '\0')
> + return false;
> +
> + break;
> + }
> + }
Both applied, thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-10-26 21:17 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-26 20:35 [PATCH 1/2] util: add util_ip_prefix_tohl James Prestwood
2020-10-26 20:35 ` [PATCH 2/2] unit: add test for util_ip_prefix_tohl James Prestwood
2020-10-26 21:17 ` [PATCH 1/2] util: add util_ip_prefix_tohl Denis Kenzior
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.