* [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.