summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikeb <mikeb@openbsd.org>2016-12-09 17:24:55 +0000
committermikeb <mikeb@openbsd.org>2016-12-09 17:24:55 +0000
commit0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1 (patch)
treecdbe4f28b0747af02e6ebe560f851091d4d8d4be
parentlog connections dropped in excess of MaxStartups at verbose LogLevel; (diff)
downloadwireguard-openbsd-0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1.tar.xz
wireguard-openbsd-0f3f7c4ee0345c0e321d5c6f0b708f4f7d37dbf1.zip
New XenStore public API function to read numeric values
A need for a function to perform string to number conversion arose when domain identifier needed to be read and converted to numerical representation. With xbf(4) the usage became broader as greater values (such as the sector count) needed to be converted. And as a result another function was implemented to perform string to unsigned long long conversion but unfortunately multiplication overflows were not handled correctly. This new version consolidates the code in one place and exports a proper XenStore API function to get and set numeric values. The new atoull function borrows multiplication overflow detection logic from the libc.
-rw-r--r--sys/dev/pv/xenstore.c70
-rw-r--r--sys/dev/pv/xenvar.h4
2 files changed, 72 insertions, 2 deletions
diff --git a/sys/dev/pv/xenstore.c b/sys/dev/pv/xenstore.c
index b55e934dfe4..fa057682ab9 100644
--- a/sys/dev/pv/xenstore.c
+++ b/sys/dev/pv/xenstore.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenstore.c,v 1.35 2016/12/07 15:21:04 mikeb Exp $ */
+/* $OpenBSD: xenstore.c,v 1.36 2016/12/09 17:24:55 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -863,6 +863,74 @@ xs_watch(void *xsc, const char *path, const char *property, struct task *task,
return (0);
}
+static unsigned long long
+atoull(const char *cp, int *error)
+{
+ unsigned long long res, cutoff;
+ int ch;
+ int cutlim;
+
+ res = 0;
+ cutoff = ULLONG_MAX / (unsigned long long)10;
+ cutlim = ULLONG_MAX % (unsigned long long)10;
+
+ do {
+ if (*cp < '0' || *cp > '9') {
+ *error = EINVAL;
+ return (res);
+ }
+ ch = *cp - '0';
+ if (res > cutoff || (res == cutoff && ch > cutlim)) {
+ *error = ERANGE;
+ return (res);
+ }
+ res *= 10;
+ res += ch;
+ } while (*(++cp) != '\0');
+
+ *error = 0;
+ return (res);
+}
+
+int
+xs_getnum(void *xsc, const char *path, const char *property,
+ unsigned long long *val)
+{
+ char *buf;
+ int error = 0;
+
+ buf = malloc(XS_MAX_PAYLOAD, M_DEVBUF, M_ZERO |
+ (cold ? M_NOWAIT : M_WAITOK));
+ if (buf == NULL)
+ return (ENOMEM);
+
+ error = xs_getprop(xsc, path, property, buf, XS_MAX_PAYLOAD);
+ if (error)
+ goto out;
+
+ *val = atoull(buf, &error);
+ if (error)
+ goto out;
+
+ out:
+ free(buf, M_DEVBUF, XS_MAX_PAYLOAD);
+ return (error);
+}
+
+int
+xs_setnum(void *xsc, const char *path, const char *property,
+ unsigned long long val)
+{
+ char buf[32];
+ int ret;
+
+ ret = snprintf(buf, sizeof(buf), "%llu", val);
+ if (ret == -1 || ret >= sizeof(buf))
+ return (ERANGE);
+
+ return (xs_setprop(xsc, path, property, buf, strlen(buf)));
+}
+
int
xs_getprop(void *xsc, const char *path, const char *property, char *value,
int size)
diff --git a/sys/dev/pv/xenvar.h b/sys/dev/pv/xenvar.h
index 5d7bf147a7c..5c97d142b7f 100644
--- a/sys/dev/pv/xenvar.h
+++ b/sys/dev/pv/xenvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xenvar.h,v 1.42 2016/12/07 15:21:04 mikeb Exp $ */
+/* $OpenBSD: xenvar.h,v 1.43 2016/12/09 17:24:55 mikeb Exp $ */
/*
* Copyright (c) 2015 Mike Belopuhov
@@ -176,6 +176,8 @@ int xs_cmd(struct xs_transaction *, int, const char *, struct iovec **,
void xs_resfree(struct xs_transaction *, struct iovec *, int);
int xs_watch(void *, const char *, const char *, struct task *,
void (*)(void *), void *);
+int xs_getnum(void *, const char *, const char *, unsigned long long *);
+int xs_setnum(void *, const char *, const char *, unsigned long long);
int xs_getprop(void *, const char *, const char *, char *, int);
int xs_setprop(void *, const char *, const char *, char *, int);
int xs_kvop(void *, int, char *, char *, size_t);