From e8fa0f662f2541952e745d9c7fff0eeaec538a5c Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 27 Jan 2021 15:22:20 +0100 Subject: ipc: read trailing responses after set operation Signed-off-by: Jason A. Donenfeld --- src/ipc-uapi.h | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'src/ipc-uapi.h') diff --git a/src/ipc-uapi.h b/src/ipc-uapi.h index d2ba522..f582916 100644 --- a/src/ipc-uapi.h +++ b/src/ipc-uapi.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -30,8 +31,10 @@ static int userspace_set_device(struct wgdevice *dev) struct wgpeer *peer; struct wgallowedip *allowedip; FILE *f; - int ret; + int ret, set_errno = -EPROTO; socklen_t addr_len; + size_t line_buffer_len = 0, line_len; + char *key = NULL, *value; f = userspace_interface_file(dev->name); if (!f) @@ -92,10 +95,30 @@ static int userspace_set_device(struct wgdevice *dev) fprintf(f, "\n"); fflush(f); - if (fscanf(f, "errno=%d", &ret) != 1) - ret = errno ? -errno : -EPROTO; - if (getc(f) != '\n' || getc(f) != '\n') - ret = -EPROTO; + while (getline(&key, &line_buffer_len, f) > 0) { + line_len = strlen(key); + ret = set_errno; + if (line_len == 1 && key[0] == '\n') + goto out; + value = strchr(key, '='); + if (!value || line_len == 0 || key[line_len - 1] != '\n') + break; + *value++ = key[--line_len] = '\0'; + + if (!strcmp(key, "errno")) { + long long num; + char *end; + if (value[0] != '-' && !char_is_digit(value[0])) + break; + num = strtoll(value, &end, 10); + if (*end || num > INT_MAX || num < INT_MIN) + break; + set_errno = num; + } + } + ret = errno ? -errno : -EPROTO; +out: + free(key); fclose(f); errno = -ret; return ret; -- cgit v1.2.3-59-g8ed1b