~blainsmith/hare-icmp

ee75a4c366b7c2d4cd90b81fc230212b91ff678f — Blain Smith 1 year, 3 months ago
init

Signed-off-by: Blain Smith <rebelgeek@blainsmith.com>
7 files changed, 230 insertions(+), 0 deletions(-)

A LICENSE
A Makefile
A README.md
A net/icmp/+test.ha
A net/icmp/message.ha
A net/icmp/v4.ha
A net/icmp/v6.ha
A  => LICENSE +21 -0
@@ 1,21 @@
MIT License

Copyright (c) 2022 Blain Smith

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file

A  => Makefile +36 -0
@@ 1,36 @@
.POSIX:
.SUFFIXES:
HARE=hare
HAREFLAGS=
HAREDOC=haredoc

DESTDIR=
PREFIX=/usr/local
SRCDIR=$(PREFIX)/src
HARESRCDIR=$(SRCDIR)/hare
THIRDPARTYDIR=$(HARESRCDIR)/third-party

all:
	@true # no-op

check:
	$(HARE) test

clean:
	rm -rf docs

docs:
	mkdir -p docs/net/icmp
	$(HAREDOC) -Fhtml net > docs/net/index.html
	$(HAREDOC) -Fhtml net::icmp > docs/net/icmp/index.html

install:
	mkdir -p "$(DESTDIR)$(THIRDPARTYDIR)"/net
	mkdir -p "$(DESTDIR)$(THIRDPARTYDIR)"/net/icmp
	install -m644 net/icmp/README "$(DESTDIR)$(THIRDPARTYDIR)"/net/icmp/README
	install -m644 net/icmp/*.ha "$(DESTDIR)$(THIRDPARTYDIR)"/net/icmp

uninstall:
	rm -rf $(DESTDIR)$(THIRDPARTYDIR)/net

.PHONY: all docs clean check install uninstall
\ No newline at end of file

A  => README.md +23 -0
@@ 1,23 @@
# WIP: hare-icmp

This package provides ICMP support for Hare.

## Installation

### From your distribution

The recommended name for this package is "hare-icmp". Look for this, or
something similar, in your local package manager. This is the preferred way to
install this package.

### System-wide installation

```
make install
```

### Vendoring

```
git subtree -P vendor/hare-icmp/ add https://git.sr.ht/~blainsmith/hare-icmp master
```
\ No newline at end of file

A  => net/icmp/+test.ha +3 -0
@@ 1,3 @@
@test fn message() void = {
    assert(1 == 1);
};
\ No newline at end of file

A  => net/icmp/message.ha +91 -0
@@ 1,91 @@
use endian;

// Either IPv4 or IPv6
export type proto = int;

type msgtype = int;

// The ICMP [[message]] body for specific types
export type body = (raw | echo | reply | destination_unreachable | time_exeeded | parameter_problem);

// A complete ICMP message
export type message = struct {
    proto: proto,
    code: int,
    checksum: int,
    body: body,
};

// A raw [[body]] of data in an ICMP message
export type raw = struct {
    data: []u8,
};

// An echo request message [[body]]
export type echo = struct {
    id: int,
    seq: int,
    data: []u8,
};

// An echo reply message [[body]]
export type reply = struct {
    id: int,
    seq: int,
    data: []u8,
};

// A destination unreachable reply message [[body]]
export type destination_unreachable = struct {
    data: []u8,
};

// A time exceeded reply message [[body]]
export type time_exeeded = struct {
    data: []u8,
};

// A parameter problem reply message [[body]]
export type parameter_problem = struct {
    pointer: uintptr,
    data: []u8,
};

// Encodes a [[message]] into a slice of bytes ready to be transmitted over the wire
export fn encode(in: *message, out: []u8) void = {
    return;
};

// Decodes a slice of bytes from the wire into a [[message]]
export fn decode(out: *message, in: []u8) void = {
    out.code = in[1]: int;
    out.checksum = endian::begetu16(in[2..4]): int;

    switch (in[0]: msgtype) {
    case V4_ECHO, V6_ECHO_REQUEST =>
        out.body = echo {
            id = endian::begetu16(in[4..6]): int,
            seq = endian::begetu16(in[6..8]): int,
            data = in[8..],
        };
    case V4_ECHO_REPLY, V6_ECHO_REPLY =>
        out.body = reply {
            id = endian::begetu16(in[4..6]): int,
            seq = endian::begetu16(in[6..8]): int,
            data = in[8..],
        };
    case V4_DESTINATION_UNREACHABLE, V6_DESTINATION_UNREACHABLE =>
        out.body = destination_unreachable { data = in[4..] };
    case V4_TIME_EXCEEDED, V6_TIME_EXCEEDED =>
        out.body = time_exeeded { data = in[4..] };
    case V4_PARAMETER_PROBLEM, V6_PARAMETER_PROBLEM =>
        out.body = parameter_problem { 
            pointer = in[4]: uintptr,
            data = in[5..],
        };
    case =>
        out.body = raw { data = in[4..] };
    };

    return;
};
\ No newline at end of file

A  => net/icmp/v4.ha +16 -0
@@ 1,16 @@
// IPv4 IANA protocol code
export def IP_V4: proto = 1;

def V4_ECHO_REPLY: msgtype = 0;
def V4_DESTINATION_UNREACHABLE: msgtype = 3;
def V4_REDIRECT: msgtype = 5;
def V4_ECHO: msgtype = 8;
def V4_ROUTER_ADVERTISEMENT: msgtype = 9;
def V4_ROUTER_SOLICITATION: msgtype = 10;
def V4_TIME_EXCEEDED: msgtype = 11;
def V4_PARAMETER_PROBLEM: msgtype = 12;
def V4_TIMESTAMP: msgtype = 13;
def V4_TIMESTAMP_REPLY: msgtype = 14;
def V4_PHOTURIS: msgtype = 40;
def V4_EXTENDED_ECHO_REQUEST: msgtype = 42;
def V4_EXTENDED_ECHO_REPLY: msgtype = 43;
\ No newline at end of file

A  => net/icmp/v6.ha +40 -0
@@ 1,40 @@
// IPv6 IANA protocol code
export def IP_V6: proto = 58;

def V6_DESTINATION_UNREACHABLE: msgtype = 1;
def V6_PACKET_TOO_BIG: msgtype = 2;
def V6_TIME_EXCEEDED: msgtype = 3;
def V6_PARAMETER_PROBLEM: msgtype = 4;
def V6_ECHO_REQUEST: msgtype = 128;
def V6_ECHO_REPLY: msgtype = 129;
def V6_MULTICAST_LISTENER_QUERY: msgtype = 130;
def V6_MULTICAST_LISTENER_REPORT: msgtype = 131;
def V6_MULTICAST_LISTENER_DONE: msgtype = 132;
def V6_ROUTER_SOLICITATION: msgtype = 133;
def V6_ROUTER_ADVERTISEMENT: msgtype = 134;
def V6_NEIGHBOR_SOLICITATION: msgtype = 135;
def V6_NEIGHBOR_ADVERTISEMENT: msgtype = 136;
def V6_REDIRECT: msgtype = 137;
def V6_ROUTER_RENUMBERING: msgtype = 138;
def V6_NODE_INFORMATION_QUERY: msgtype = 139;
def V6_NODE_INFORMATION_RESPONSE: msgtype = 140;
def V6_INVERSE_NEIGHBOR_DISCOVERY_SOLICITATION: msgtype = 141;
def V6_INVERSE_NEIGHBOR_DISCOVERY_ADVERTISEMENT: msgtype = 142;
def V6_VERSION2_MULTICAST_LISTENER_REPORT: msgtype = 143;
def V6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST: msgtype = 144;
def V6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY: msgtype = 145;
def V6_MOBILE_PREFIX_SOLICITATION: msgtype = 146;
def V6_MOBILE_PREFIX_ADVERTISEMENT: msgtype = 147;
def V6_CERTIFICATION_PATH_SOLICITATION: msgtype = 148;
def V6_CERTIFICATION_PATH_ADVERTISEMENT: msgtype = 149;
def V6_MULTICAST_ROUTER_ADVERTISEMENT: msgtype = 151;
def V6_MULTICAST_ROUTER_SOLICITATION: msgtype = 152;
def V6_MULTICAST_ROUTER_TERMINATION: msgtype = 153;
def V6_FMI_PV6: msgtype = 154;
def V6_RPL_CONTROL: msgtype = 155;
def V6_ILNP_V6_LOCATOR_UPDATE: msgtype = 156;
def V6_DUPLICATE_ADDRESS_REQUEST: msgtype = 157;
def V6_DUPLICATE_ADDRESS_CONFIRMATION: msgtype = 158;
def V6_MPL_CONTROL: msgtype = 159;
def V6_EXTENDED_ECHO_REQUEST: msgtype = 160;
def V6_EXTENDED_ECHO_REPLY: msgtype = 161;
\ No newline at end of file