/* * 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 #include #include #include #include #include #include enum { TYPE, CHECKSUM = 2, ID = 4, SEQ_NUM = 6, DATA = 8 }; #if 0 static int get_type(struct wip_icmp *const icmp, const unsigned char *const p, const size_t n) { unsigned char type; if (icmp->read) return 0; type = p[0]; if (type != ECHO_REQUEST) return -1; wip_log("%s: got echo request\n"); icmp->type = type; return 0; } static void get_checksum(struct wip_icmp *const icmp, const unsigned char *const p, const size_t n) { size_t off; struct wip_be16 v; enum {END = CHECKSUM + sizeof v}; if (icmp->read >= END || n < END - icmp->read) return; off = CHECKSUM - icmp->read; v.v[0] = p[off]; v.v[1] = p[off + 1]; icmp->exp_checksum = wip_be16(&v); } static void get_id(struct wip_icmp *const icmp, const unsigned char *const p, const size_t n) { size_t off; struct wip_be16 v; enum {END = ID + sizeof v}; if (icmp->read >= END || n < END - icmp->read) return; off = ID - icmp->read; v.v[0] = p[off]; v.v[1] = p[off + 1]; icmp->id = wip_be16(&v); } static void get_seqnum(struct wip_icmp *const icmp, const unsigned char *const p, const size_t n) { size_t off; struct wip_be16 v; enum {END = SEQ_NUM + sizeof v}; if (icmp->read >= END || n < END - icmp->read) return; off = SEQ_NUM - icmp->read; v.v[0] = p[off]; v.v[1] = p[off + 1]; icmp->seqnum = wip_be16(&v); wip_log("chksum=%#x, id=%#x, seq_num=%#x\n", icmp->exp_checksum, icmp->id, icmp->seqnum); } static enum wip_state get_data(struct wip *const w, struct wip_icmp *const icmp, const unsigned char *const p, const size_t n) { const struct wip_cfg *const cfg = &w->cfg; const size_t offset = icmp->read + n; const void *src = p; size_t sz = n; if (offset < DATA) return WIP_OK; else if (!icmp->buf) { sz = n - DATA - icmp->read; src = p + DATA - icmp->read; if (!(icmp->buf = cfg->alloc(sz, cfg->user))) return WIP_FATAL; } else { const size_t nsz = icmp->n + n; enum {MAXSZ = 40}; void *buf; if (nsz > MAXSZ) return WIP_INVALID; else if (!(buf = cfg->realloc(icmp->buf, nsz, cfg->user))) return WIP_FATAL; icmp->buf = buf; } memcpy((char *)icmp->buf + icmp->read, src, sz); icmp->n += sz; wip_log("data (%lu bytes): {", (unsigned long)icmp->n); { size_t i; for (i = 0; i < icmp->n; i++) { wip_log("%#hhx", *((const char *)icmp->buf + i)); if (i + 1 < icmp->n) wip_log(", "); } } wip_log("}\n"); return WIP_OK; } #endif enum wip_state wip_icmp_rx(struct wip *const w, const void *buf, size_t n, void *const args) { struct wip_icmp *const icmp = args; enum wip_state ret; size_t r; while ((ret = icmp->next(w, buf, n, icmp, &r)) == WIP_AGAIN) { buf = (const char *)buf + r; n -= r; } return ret; #if 0 enum wip_state (*next)(struct wip *, const void *, size_t, struct wip_icmp *) const struct wip_rx_sm_h *const h = &w->rx.sm.h; const unsigned char *const p = buf; const unsigned short dlen = wip_be16(&h->len) - h->header_sz; enum wip_state ret; size_t i; if (get_type(icmp, buf, n)) return 0; get_checksum(icmp, buf, n); get_id(icmp, buf, n); get_seqnum(icmp, buf, n); if ((ret = get_data(w, icmp, buf, n))) return ret; for (i = 0; i < n; i++) /* Avoid suming checksum */ if (icmp->read >= CHECKSUM || ((i != 2) && (i != 3))) icmp->checksum += p[i]; if (icmp->read += n >= dlen) { wip_log("expected checksum=%#x, got=%#x\n", icmp->exp_checksum, icmp->checksum); } return WIP_OK; #endif }