summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2017-07-17 06:32:53 +0000
committerdlg <dlg@openbsd.org>2017-07-17 06:32:53 +0000
commit38a8dfe4fa2485994d033b721074b577f1aa84b7 (patch)
treefe3f95d7302613556817860da0d208f3d1efba7b
parentFix missing splx() in iwm_newstate_task(). Bug introduced 2 hours ago in r1.200. (diff)
downloadwireguard-openbsd-38a8dfe4fa2485994d033b721074b577f1aa84b7.tar.xz
wireguard-openbsd-38a8dfe4fa2485994d033b721074b577f1aa84b7.zip
add support for binary sysctl payloads by handling them as hex strings.
this was part of a demo showing how to implement the kernel side of sysctl(3) for setting Semantically Opaque Interface Identifier key material, but it seems to be the most straightforward path toward integrating soiikey handling and rc. ok florian@ sthen@ naddy@ tb@
-rw-r--r--sbin/sysctl/sysctl.c107
1 files changed, 100 insertions, 7 deletions
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 94f78c0d673..39588ee6516 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.c,v 1.226 2017/04/25 17:33:16 tb Exp $ */
+/* $OpenBSD: sysctl.c,v 1.227 2017/07/17 06:32:53 dlg Exp $ */
/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */
/*
@@ -182,6 +182,8 @@ int Aflag, aflag, nflag, qflag;
/* prototypes */
void debuginit(void);
void listall(char *, struct list *);
+int parse_hex_char(char);
+ssize_t parse_hex_string(unsigned char *, size_t, const char *);
void parse(char *, int);
void parse_baddynamic(int *, size_t, char *, void **, size_t *, int, int);
void usage(void);
@@ -286,6 +288,53 @@ listall(char *prefix, struct list *lp)
}
}
+int
+parse_hex_char(char ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return (ch - '0');
+
+ ch = tolower(ch);
+ if (ch >= 'a' && ch <= 'f')
+ return (ch - 'a' + 10);
+
+ return (-1);
+}
+
+ssize_t
+parse_hex_string(unsigned char *dst, size_t dstlen, const char *src)
+{
+ ssize_t len = 0;
+ int digit;
+
+ while (len < dstlen) {
+ if (*src == '\0')
+ return (len);
+
+ digit = parse_hex_char(*src++);
+ if (digit == -1)
+ return (-1);
+ dst[len] = digit << 4;
+
+ digit = parse_hex_char(*src++);
+ if (digit == -1)
+ return (-1);
+
+ dst[len] |= digit;
+ len++;
+ }
+
+ while (*src != '\0') {
+ if (parse_hex_char(*src++) == -1 ||
+ parse_hex_char(*src++) == -1)
+ return (-1);
+
+ len++;
+ }
+
+ return (len);
+}
+
/*
* Parse a name into a MIB entry.
* Lookup and print out the MIB entry if it exists.
@@ -302,6 +351,7 @@ parse(char *string, int flags)
struct list *lp;
int mib[CTL_MAXNAME];
char *cp, *bufp, buf[SYSCTL_BUFSIZ];
+ unsigned char hex[SYSCTL_BUFSIZ];
(void)strlcpy(buf, string, sizeof(buf));
bufp = buf;
@@ -566,6 +616,11 @@ parse(char *string, int flags)
len = sysctl_inet6(string, &bufp, mib, flags, &type);
if (len < 0)
return;
+#ifdef IPV6CTL_SOIIKEY
+ if (mib[2] == IPPROTO_IPV6 &&
+ mib[3] == IPV6CTL_SOIIKEY)
+ special |= HEX;
+#endif
if ((mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMFC) ||
(mib[2] == IPPROTO_IPV6 && mib[3] == IPV6CTL_MRTMIF) ||
@@ -717,6 +772,27 @@ parse(char *string, int flags)
newval = &quadval;
newsize = sizeof(quadval);
break;
+ case CTLTYPE_STRING:
+ if (special & HEX) {
+ ssize_t len;
+
+ len = parse_hex_string(hex, sizeof(hex),
+ newval);
+ if (len == -1) {
+ warnx("%s: hex string %s: invalid",
+ string, newval);
+ return;
+ }
+ if (len > sizeof(hex)) {
+ warnx("%s: hex string %s: too long",
+ string, newval);
+ return;
+ }
+
+ newval = hex;
+ newsize = len;
+ }
+ break;
}
}
size = (special & SMALLBUF) ? 512 : SYSCTL_BUFSIZ;
@@ -936,13 +1012,30 @@ parse(char *string, int flags)
if (newval == NULL) {
if (!nflag)
(void)printf("%s%s", string, equ);
- (void)puts(buf);
- } else {
- if (!qflag) {
- if (!nflag)
- (void)printf("%s: %s -> ", string, buf);
- (void)puts((char *)newval);
+ if (special & HEX) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ (void)printf("%02x",
+ (unsigned char)buf[i]);
+ }
+ (void)printf("\n");
+ } else
+ (void)puts(buf);
+ } else if (!qflag) {
+ if (!nflag) {
+ (void)printf("%s: ", string);
+ if (special & HEX) {
+ size_t i;
+ for (i = 0; i < size; i++) {
+ (void)printf("%02x",
+ (unsigned char)buf[i]);
+ }
+ } else
+ (void)printf("%s", cp);
+
+ (void)printf(" -> ");
}
+ (void)puts(cp);
}
return;