summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/utils.c181
-rw-r--r--accel-pppd/utils.h14
2 files changed, 195 insertions, 0 deletions
diff --git a/accel-pppd/utils.c b/accel-pppd/utils.c
index 3b87ee1..544c59e 100644
--- a/accel-pppd/utils.c
+++ b/accel-pppd/utils.c
@@ -1,7 +1,11 @@
+#include <arpa/inet.h>
+#include <ctype.h>
#include <errno.h>
#include <netdb.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
@@ -12,6 +16,21 @@
extern int urandom_fd;
+/* Convenient wrapper around inet_ntop() to print IPv6 addresses.
+ * It stores a string representation of addr into buf, which must be at
+ * least INET6_ADDRSTRLEN bytes long.
+ *
+ * Returns buf, which is guaranteed to contain a valid string even if an error
+ * occured.
+ */
+char __export *u_ip6str(const struct in6_addr *addr, char *buf)
+{
+ if (!inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN))
+ snprintf(buf, INET6_ADDRSTRLEN, "< ERROR! >");
+
+ return buf;
+}
+
void __export u_inet_ntoa(in_addr_t addr, char *str)
{
addr = ntohl(addr);
@@ -37,6 +56,117 @@ int __export u_readlong(long int *dst, const char *src,
}
}
+/* Parse spaces.
+ * Returns the number of leading space characters in str.
+ * This is a convenient function around strspn() which preserves the look and
+ * feel of other u_parse_*() functions.
+ */
+size_t __export u_parse_spaces(const char *str)
+{
+ return strspn(str, " ");
+}
+
+/* Parse end of string.
+ * Reads a sequence of space characters, followed by the end-of-string
+ * mark ('\0').
+ * Returns the number of characters parsed on success (that is, the number of
+ * space characters plus one for '\0'). Beware that 'str + u_parse_eos(str)'
+ * points to the next byte after the end of the string in this case.
+ * Returns 0 if parsing fails (that is, if unexpected characers are found
+ * before the end of the string).
+ */
+size_t __export u_parse_endstr(const char *str)
+{
+ const char *end;
+
+ end = str + strspn(str, " ");
+ if (*end != '\0')
+ return 0;
+
+ ++end;
+
+ return end - str;
+}
+
+/* Parse an 8 bits unsigned integer in base 10.
+ * Returns the number of bytes parsed on success.
+ * Returns 0 if str doesn't start with a valid number or if this number doesn't
+ * fit in 8 bits.
+ */
+size_t __export u_parse_u8(const char *str, uint8_t *val)
+{
+ char *endptr;
+ unsigned long ul;
+
+ /* strtoul() handles leading signs (+/-) and white spaces. Make sure we
+ * parse raw numbers.
+ */
+ if (!isdigit(*str))
+ return 0;
+
+ ul = strtoul(str, &endptr, 10);
+ if (ul > UINT8_MAX)
+ return 0;
+
+ *val = ul;
+
+ return endptr - str;
+}
+
+/* Parse a 16 bits unsigned integer in base 10.
+ * Returns the number of bytes parsed on success.
+ * Returns 0 if str doesn't start with a valid number or if this number doesn't
+ * fit in 16 bits.
+ */
+size_t __export u_parse_u16(const char *str, uint16_t *val)
+{
+ char *endptr;
+ unsigned long ul;
+
+ /* strtoul() handles leading signs (+/-) and white spaces. Make sure we
+ * parse raw numbers.
+ */
+ if (!isdigit(*str))
+ return 0;
+
+ ul = strtoul(str, &endptr, 10);
+ if (ul > UINT16_MAX)
+ return 0;
+
+ *val = ul;
+
+ return endptr - str;
+}
+
+/* Parse a 32 bits unsigned integer in base 10.
+ * Returns the number of bytes parsed on success.
+ * Returns 0 if str doesn't start with a valid number or if this number doesn't
+ * fit in 32 bits.
+ */
+size_t __export u_parse_u32(const char *str, uint32_t *val)
+{
+ char *endptr;
+ unsigned long ul;
+
+ /* strtoul() handles leading signs (+/-) and white spaces. Make sure we
+ * parse raw numbers.
+ */
+ if (!isdigit(*str))
+ return 0;
+
+ errno = 0;
+ ul = strtoul(str, &endptr, 10);
+ /* On platforms where unsigned longs are 32 bits wide, overflows would
+ * return a valid UINT32_MAX value. So we need to check for ERANGE too.
+ */
+ if (errno == ERANGE || ul > UINT32_MAX)
+ return 0;
+
+ *val = ul;
+
+ return endptr - str;
+}
+
int __export u_parse_ip4addr(const char *src, struct in_addr *addr,
const char **err_msg)
{
@@ -62,6 +192,57 @@ int __export u_parse_ip4addr(const char *src, struct in_addr *addr,
return 0;
}
+/* Parse an IPv6 address (for example "2001:db8::1").
+ * Returns the number of bytes parsed, or 0 if str doesn't start with an IPv6
+ * address.
+ */
+size_t __export u_parse_ip6addr(const char *str, struct in6_addr *addr)
+{
+ char buf[INET6_ADDRSTRLEN];
+ size_t len;
+
+ len = strspn(str, ":0123456789abcdef");
+ if (!len || len >= sizeof(buf))
+ return 0;
+
+ memcpy(buf, str, len);
+ buf[len] = '\0';
+
+ if (inet_pton(AF_INET6, buf, addr) != 1)
+ return 0;
+
+ return len;
+}
+
+/* Parse an IPv6 network prefix in CIDR notation (for example "2001:db8::/32").
+ * Returns the number of bytes parsed, or 0 if str doesn't start with an IPv6
+ * network prefix.
+ */
+size_t __export u_parse_ip6cidr(const char *str, struct in6_addr *netp, uint8_t *plen)
+{
+ const char *ptr = str;
+ size_t len;
+
+ len = u_parse_ip6addr(ptr, netp);
+ if (!len)
+ return 0;
+
+ ptr += len;
+ if (*ptr != '/')
+ return 0;
+
+ len = u_parse_u8(++ptr, plen);
+ if (!len)
+ return 0;
+
+ if (*plen > 128)
+ 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 8758264..d3e0608 100644
--- a/accel-pppd/utils.h
+++ b/accel-pppd/utils.h
@@ -2,11 +2,25 @@
#define __UTILS_H
#include <netinet/in.h>
+#include <stdint.h>
+
+char *u_ip6str(const struct in6_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);
+
+size_t u_parse_spaces(const char *str);
+size_t u_parse_endstr(const char *str);
+
+size_t u_parse_u8(const char *str, uint8_t *val);
+size_t u_parse_u16(const char *str, uint16_t *val);
+size_t u_parse_u32(const char *str, uint32_t *val);
+
int u_parse_ip4addr(const char *src, struct in_addr *addr,
const char **err_msg);
+size_t u_parse_ip6addr(const char *str, struct in6_addr *addr);
+size_t u_parse_ip6cidr(const char *str, struct in6_addr *netp, uint8_t *plen);
+
int u_randbuf(void *buf, size_t buf_len, int *err);
#endif