From 10e298b1c2926634592d1a3fc6f8d35615073d32 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 15 Aug 2022 18:34:50 +0100 Subject: [PATCH] prefork-interp: New protocol: C: more negotiation-ness etc. Signed-off-by: Ian Jackson --- cprogs/prefork-interp.c | 47 ++++++++++++++++++++++++++++++----------- cprogs/prefork.c | 2 ++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/cprogs/prefork-interp.c b/cprogs/prefork-interp.c index 338e60e..4883a2d 100644 --- a/cprogs/prefork-interp.c +++ b/cprogs/prefork-interp.c @@ -280,15 +280,36 @@ static bool was_eof(FILE *call_sock) { return feof(call_sock) || errno==ECONNRESET; } -// Does protocol exchange. Returns 0 if OK, error msg if peer was garbage. -static const char *protocol_exchange(FILE *call_sock) { - char ack; - size_t sr = fread(&ack, sizeof(ack), 1, call_sock); +// Returns -1 on EOF +static int protocol_read_maybe(FILE *call_sock, void *data, size_t sz) { + size_t sr = fread(data, sz, 1, call_sock); if (sr != 1) { - if (was_eof(call_sock)) return "initial monitor process quit"; - diee("read() ack byte"); + if (was_eof(call_sock)) return -1; + diee("read() on monitor call socket"); } - if (ack != '\n') die("got ack byte 0x%02x, not '\n'", ack); + return 0; +} + +static void protocol_read(FILE *call_sock, void *data, size_t sz) { + if (protocol_read_maybe(call_sock, data, sz) < 0) + die("monitor process quit unexpectedly"); +} + +// Does protocol exchange. Returns 0 if OK, error msg if peer was garbage. +static const char *protocol_exchange(FILE *call_sock) { + char magic[sizeof(header_magic)]; + + if (protocol_read_maybe(&magic, sizeof(magic)) < 0) + return "initial monitor process quit"; + + if (memcmp(header, header_magic, sizeof(header_magic))) + die("got unexpected protocol magic 0x%04lx", + header[0], header[1], header[2], header[3]); + + uint32_t xdata_len; + protocol_read(&xdata_len, sizeof(xdata_len)); + void *xdata = xmalloc(xdata_len); + protocol_read(xdata, xdata_len); // We're committed now, send the request (or bail out) send_request(call_sock); @@ -336,6 +357,12 @@ void become_setup(int sfd, int fake_pair[2]) { if (dup2(null_0, 0)) diee("dup2 /dev/null onto stdin"); if (dup2(2, 1) != 1) die("dup2 stderr onto stdout"); + // Extension could work like this: + // + // We advertise a new protocol (perhaps one which is nearly entirely + // different after the connect) by putting a name for it comma-separated + // next to "v1". Simple extension can be done by having the script + // side say something about it in the ack xdata, which we currently ignore. putenv(m_asprintf("PREFORK_INTERP=v1 %d,%d %s", sfd, call_fd, socket_path)); @@ -441,11 +468,7 @@ int main(int argc_unused, const char *const *argv) { FILE *call_sock = connect_or_spawn(); uint32_t status; - ssize_t sr = fread(&status, sizeof(status), 1, call_sock); - if (sr != 1) { - if (was_eof(call_sock)) die("per-call server monitor process quit"); - diee("read status from call socket"); - } + protocol_read(&status, sizeof(status); status = ntohl(status); if (status > INT_MAX) die("status 0x%lx does not fit in an int", diff --git a/cprogs/prefork.c b/cprogs/prefork.c index 909d065..08958ce 100644 --- a/cprogs/prefork.c +++ b/cprogs/prefork.c @@ -10,6 +10,8 @@ static uid_t us; static const char *run_base; static const char *run_base_mkdir_p; +static const char header_magic[4] = "PFI\n"; + void common_diee(const char *m) { diee("%s", m); } void common_die (const char *m) { die ("%s", m); } -- 2.30.2