aboutsummaryrefslogtreecommitdiff
path: root/src/protocol/icmp/start.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-09-09 03:14:50 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-09-18 01:08:14 +0200
commitc11cb04929f28853142b14339b66f561ca028f36 (patch)
treea77a3ddcc1d01028e4077cb295b9b41f594c5d52 /src/protocol/icmp/start.c
First commitHEADmaster
Diffstat (limited to 'src/protocol/icmp/start.c')
-rw-r--r--src/protocol/icmp/start.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/protocol/icmp/start.c b/src/protocol/icmp/start.c
new file mode 100644
index 0000000..f50052e
--- /dev/null
+++ b/src/protocol/icmp/start.c
@@ -0,0 +1,205 @@
+/*
+ * wip, a small TCP/IP stack.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include <wip/wip.h>
+#include <wip/prv/io.h>
+#include <wip/prv/log.h>
+#include <wip/prv/icmp.h>
+#include <wip/prv/icmp/routines.h>
+#include <wip/prv/icmp/types.h>
+#include <stddef.h>
+#include <string.h>
+
+struct read
+{
+ const void *buf;
+ size_t n;
+ struct wip_icmp *icmp;
+};
+
+static int io_read(void *const buf, const size_t n, void *const user)
+{
+ const struct read *const r = user;
+ const size_t ret = n > r->n ? r->n : n;
+
+ memcpy(buf, r->buf, ret);
+ return ret;
+}
+
+static enum wip_state readbuf(struct wip_sm_io *const io, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp)
+{
+ struct wip_cfg cfg = {0};
+ struct read r;
+
+ r.buf = buf;
+ r.n = n;
+ r.icmp = icmp;
+
+ cfg.read = io_read;
+ cfg.user = &r;
+ return wip_io_read_c(&cfg, io);
+}
+
+enum wip_state get_payload(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ const struct wip_cfg *const cfg = &w->cfg;
+ const size_t nsz = icmp->read + n;
+ char *const nbuf = cfg->realloc(icmp->buf, nsz, cfg->user);
+ size_t i;
+
+ if (!nbuf)
+ return WIP_FATAL;
+
+ memcpy(nbuf + icmp->read, buf, n);
+ icmp->buf = nbuf;
+ icmp->read += n;
+ *r = n;
+
+ for (i = icmp->read; i < nsz; i++)
+ icmp->checksum += *(const char *)icmp->buf;
+
+ wip_log("ICMP data={");
+
+ for (i = 0; i < icmp->read; i++)
+ {
+ wip_log("%#hhx", *((const char *)icmp->buf + i));
+
+ if (i + 1 < icmp->read)
+ wip_log(", ");
+ }
+
+ wip_log("}\n");
+
+ wip_log("calculated checksum: %#hx, expected checksum: %#hx\n",
+ icmp->checksum, wip_be16(&icmp->exp_checksum));
+ return WIP_OK;
+}
+
+enum wip_state get_seqnum(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ const enum wip_state state = readbuf(&icmp->io, buf, n, icmp);
+
+ if (state)
+ return state;
+ else
+ {
+ struct wip_sm_io io = {0};
+
+ io.buf = &icmp->seqnum;
+ io.n = sizeof icmp->seqnum;
+ icmp->io = io;
+ }
+
+ wip_log("got seqnum: %#x\n", wip_be16(&icmp->seqnum));
+ icmp->checksum += wip_be16(&icmp->seqnum);
+ icmp->next = get_payload;
+ *r = sizeof icmp->seqnum;
+ return WIP_AGAIN;
+}
+
+enum wip_state get_id(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ const enum wip_state state = readbuf(&icmp->io, buf, n, icmp);
+
+ if (state)
+ return state;
+ else
+ {
+ struct wip_sm_io io = {0};
+
+ io.buf = &icmp->seqnum;
+ io.n = sizeof icmp->seqnum;
+ icmp->io = io;
+ }
+
+ wip_log("got id: %#x\n", wip_be16(&icmp->id));
+ icmp->checksum += wip_be16(&icmp->id);
+ icmp->next = get_seqnum;
+ *r = sizeof icmp->id;
+ return WIP_AGAIN;
+}
+
+enum wip_state get_checksum(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ const enum wip_state state = readbuf(&icmp->io, buf, n, icmp);
+
+ if (state)
+ return state;
+ else
+ {
+ struct wip_sm_io io = {0};
+
+ io.buf = &icmp->id;
+ io.n = sizeof icmp->id;
+ icmp->io = io;
+ }
+
+ wip_log("got expected checksum: %#x\n", wip_be16(&icmp->exp_checksum));
+ icmp->next = get_id;
+ *r = sizeof icmp->exp_checksum;
+ return WIP_AGAIN;
+}
+
+enum wip_state get_code(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ unsigned char code;
+ struct wip_sm_io io = {0};
+ enum wip_state state;
+
+ io.buf = &code;
+ io.n = sizeof code;
+
+ if ((state = readbuf(&io, buf, n, icmp)))
+ return state;
+ else if (code)
+ return WIP_INVALID;
+ else
+ {
+ struct wip_sm_io nio = {0};
+
+ nio.buf = &icmp->exp_checksum;
+ nio.n = sizeof icmp->exp_checksum;
+ icmp->io = nio;
+ }
+
+ wip_log("got code\n");
+ icmp->checksum += code;
+ icmp->next = get_checksum;
+ *r = sizeof code;
+ return WIP_AGAIN;
+}
+
+enum wip_state wip_icmp_rx_start(struct wip *const w, const void *const buf,
+ const size_t n, struct wip_icmp *const icmp, size_t *const r)
+{
+ unsigned char type;
+ struct wip_sm_io io = {0};
+ enum wip_state state;
+
+ io.buf = &type;
+ io.n = sizeof type;
+
+ if ((state = readbuf(&io, buf, n, icmp)))
+ return state;
+ else if (type != ICMP_ECHO_REQUEST)
+ return WIP_INVALID;
+
+ wip_log("got echo request\n");
+ icmp->checksum += type;
+ icmp->type = type;
+ icmp->next = get_code;
+ *r = sizeof type;
+ return WIP_AGAIN;
+}