diff options
author | Guillaume Nault <g.nault@alphalink.fr> | 2018-12-07 17:37:43 +0100 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2018-12-08 07:51:36 +0300 |
commit | 093baccac54573eed54fa2650c19ecaeed3065a5 (patch) | |
tree | ace1fae4b87bcb29104b9cb11671d2bed5f8e4ab | |
parent | 0f2f775d644c4cd9007b5816c2cfa9e8d933ef6d (diff) | |
download | accel-ppp-093baccac54573eed54fa2650c19ecaeed3065a5.tar.gz accel-ppp-093baccac54573eed54fa2650c19ecaeed3065a5.zip |
utils: add IPv4 string parsing helpers
Define the IPv4 counterparts of u_ip6str() and u_parse_ip6cidr().
Also add the special u_parse_ip4range() which will be useful for
parsing the [client-ip-range] section of accel-ppp.conf.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
-rw-r--r-- | accel-pppd/utils.c | 79 | ||||
-rw-r--r-- | accel-pppd/utils.h | 3 |
2 files changed, 82 insertions, 0 deletions
diff --git a/accel-pppd/utils.c b/accel-pppd/utils.c index bf58c145..018b6efa 100644 --- a/accel-pppd/utils.c +++ b/accel-pppd/utils.c @@ -30,6 +30,21 @@ char __export *u_ip6str(const struct in6_addr *addr, char *buf) return buf; } +/* Convenient wrapper around inet_ntop() to print IPv4 addresses. + * It stores a string representation of addr into buf, which must be at + * least INET_ADDRSTRLEN bytes long. + * + * Returns buf, which is guaranteed to contain a valid string even if an error + * occured. + */ +char __export *u_ip4str(const struct in_addr *addr, char *buf) +{ + if (!inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN)) + snprintf(buf, INET_ADDRSTRLEN, "< ERROR! >"); + + return buf; +} + void __export u_inet_ntoa(in_addr_t addr, char *str) { addr = ntohl(addr); @@ -242,6 +257,70 @@ size_t __export u_parse_ip6cidr(const char *str, struct in6_addr *netp, uint8_t return ptr - str; } +/* Parse an IPv4 network prefix in CIDR notation (for example "192.0.2.0/24"). + * The IP address must be in dotted-decimal format. + * Returns the number of bytes parsed, or 0 if str doesn't start with an IPv4 + * network prefix. + */ +size_t __export u_parse_ip4cidr(const char *str, struct in_addr *netp, uint8_t *plen) +{ + const char *ptr = str; + size_t len; + + len = u_parse_ip4addr(ptr, netp); + if (!len) + return 0; + + ptr += len; + if (*ptr != '/') + return 0; + + len = u_parse_u8(++ptr, plen); + if (!len) + return 0; + + if (*plen > 32) + return 0; + + ptr += len; + + return ptr - str; +} + +/* Parse an IPv4 address range (for example "192.0.2.0-255"). + * The IP address must be in dotted-decimal format. The number following '-' + * is the upper bound of the address' least significant byte (the lower bound + * is given by the address itself). The upper bound must be bigger or equal + * than the lower bound. + * + * Returns the number of bytes parsed, or 0 if str doesn't start with an IPv4 + * address range. + */ +size_t __export u_parse_ip4range(const char *str, struct in_addr *base_ip, uint8_t *max) +{ + const char *ptr = str; + size_t len; + + len = u_parse_ip4addr(ptr, base_ip); + if (!len) + return 0; + + ptr += len; + if (*ptr != '-') + return 0; + + len = u_parse_u8(++ptr, max); + if (!len) + return 0; + + if (*max < (ntohl(base_ip->s_addr) & 0xff)) + return 0; + + ptr += len; + + return ptr - str; +} + int __export u_randbuf(void *buf, size_t buf_len, int *err) { uint8_t *u8buf = buf; diff --git a/accel-pppd/utils.h b/accel-pppd/utils.h index a7c38973..06859a6b 100644 --- a/accel-pppd/utils.h +++ b/accel-pppd/utils.h @@ -5,6 +5,7 @@ #include <stdint.h> char *u_ip6str(const struct in6_addr *addr, char *buf); +char *u_ip4str(const struct in_addr *addr, char *buf); void u_inet_ntoa(in_addr_t, char *str); int u_readlong(long int *dst, const char *src, long int min, long int max); @@ -20,6 +21,8 @@ size_t u_parse_ip6addr(const char *str, struct in6_addr *addr); size_t u_parse_ip4addr(const char *str, struct in_addr *addr); size_t u_parse_ip6cidr(const char *str, struct in6_addr *netp, uint8_t *plen); +size_t u_parse_ip4cidr(const char *str, struct in_addr *netp, uint8_t *plen); +size_t u_parse_ip4range(const char *str, struct in_addr *base_ip, uint8_t *max); int u_randbuf(void *buf, size_t buf_len, int *err); |