summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile2
-rwxr-xr-xrun_server.sh19
-rw-r--r--seqnum_server.c66
4 files changed, 86 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 21c78dc..a781ccc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
*.o
client
server
-clientd
-serverd
+seqnum_server
bak/
diff --git a/Makefile b/Makefile
index 1e2834c..b63a27b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC = gcc
CFLAGS = -Wall -Wextra -O2 -g -std=c11 -fwrapv -pthread
LDFLAGS = -pthread
-TARGETS = server client
+TARGETS = server client seqnum_server
SOURCES = $(filter-out $(patsubst %,%.c,$(TARGETS)),$(wildcard *.c))
OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
diff --git a/run_server.sh b/run_server.sh
index e6beee9..c3e9759 100755
--- a/run_server.sh
+++ b/run_server.sh
@@ -1,9 +1,26 @@
#!/usr/bin/env bash
+set -euo pipefail
+
if [[ "$(id -u)" -ne 0 ]]; then
echo >&2 "Run with sudo"
exit 1
fi
+if [[ $# -eq 0 ]]; then
+ server_exec=./server
+elif [[ $# -eq 1 ]]; then
+ server_exec="$1"
+else
+ echo >&2 "Usage: $0 [server executable]"
+ echo >&2 "By default runs ./server"
+ exit 1
+fi
+
+if [[ ! -x "$server_exec" ]]; then
+ echo >&2 "Cannot execute server executable $server_exec"
+ exit 1
+fi
+
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all
trap "echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all" EXIT
-./serverd
+"$server_exec"
diff --git a/seqnum_server.c b/seqnum_server.c
new file mode 100644
index 0000000..aa6ab42
--- /dev/null
+++ b/seqnum_server.c
@@ -0,0 +1,66 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include "icmp_server.h"
+#include "util.h"
+
+
+static const uint8_t* detect_payload(const uint8_t *data, size_t length) {
+ // Detects the 16-byte "padding" payload one can send using the ping(1) utility.
+ // This payload starts at byte 16 and repeats thereafter.
+ if (length < 32) return NULL;
+
+ // For each byte in the padding
+ for (size_t i = 0; i < 16; i++) {
+ // For each repetition
+ for (size_t j = 1; 16 + 16 * j + i < length; j++) {
+ // Assert that the padding indeed repeats
+ if (data[16 + i] != data[16 + 16 * j + i]) return NULL;
+ }
+ }
+
+ return data + 16;
+}
+
+int main() {
+ int sock = icmp_server_open_socket();
+ if (sock < 0) {
+ perror("socket (icmp_server_open_socket)");
+ return 1;
+ }
+
+ while (true) {
+ struct icmp_incoming pkt = icmp_server_receive(sock);
+ if (pkt.data == NULL) {
+ perror("recvmsg (icmp_server_receive)");
+ usleep(500000);
+ continue;
+ }
+ // xxd(stderr, pkt.data, pkt.length);
+
+ const uint8_t *payload = detect_payload(pkt.data, pkt.length);
+
+ if (payload != NULL) {
+ printf("payl");
+ fwrite(&pkt.source_addr, 1, 4, stdout);
+ fwrite(payload, 1, 16, stdout);
+ fflush(stdout);
+ uint16_t new_seqnum;
+ if (readall(STDIN_FILENO, &new_seqnum, 2) < 0) {
+ perror("read");
+ new_seqnum = pkt.seqnum;
+ }
+ pkt.seqnum = new_seqnum;
+ } else {
+ fprintf(stderr, "Echoing packet due to invalid payload\n");
+ }
+
+ int ret = icmp_server_send_reply(sock, pkt.source_addr, pkt.id, pkt.seqnum, pkt.data, pkt.length);
+ if (ret < 0) {
+ perror("sendto (icmp_server_send_reply)");
+ usleep(500000);
+ continue;
+ }
+ }
+}