mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
util: add util_ip_prefix_tohl
Parses an IP prefix notation string into prefix, start, end, and netmask. All values are returned in host order.
This commit is contained in:
parent
b7e2a98628
commit
42605c9e76
90
src/util.c
90
src/util.c
@ -28,6 +28,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <ell/ell.h>
|
#include <ell/ell.h>
|
||||||
|
|
||||||
@ -218,3 +220,91 @@ const char *util_get_username(const char *identity)
|
|||||||
|
|
||||||
return 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 = strtoul(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;
|
||||||
|
}
|
||||||
|
@ -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;
|
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 */
|
#endif /* __UTIL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user