summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--client.c2
-rw-r--r--icmp.c16
-rwxr-xr-xrun_server.sh5
-rw-r--r--server.c91
5 files changed, 66 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 84683dd..b1de31f 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ clean:
server: server.o $(OBJECTS)
- $(CC) $(CFLAGS) $^ -o $@ -lnetfilter_log
+ $(CC) $(CFLAGS) $^ -o $@
client: client.o $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $@
diff --git a/client.c b/client.c
index 527375f..1f8663f 100644
--- a/client.c
+++ b/client.c
@@ -25,6 +25,6 @@ int main(void) {
return 1;
}
- printf("Received length: %zd\nPayload:\n", reply.length);
+ printf("Received length: %zd payload:\n", reply.length);
xxd(reply.data, reply.length);
}
diff --git a/icmp.c b/icmp.c
index e64580c..63436ac 100644
--- a/icmp.c
+++ b/icmp.c
@@ -2,6 +2,7 @@
#include <stddef.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
@@ -99,10 +100,6 @@ struct icmp_reply icmp_communicate(int sock, const char *ip_address, int seqnum,
int icmp_send_echo_reply(const char *ip_address, int id, int seqnum, const void *data_, size_t length) {
const uint8_t *data = (const uint8_t*)data_;
- int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- int zero = 0;
- assert(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &zero, sizeof zero) >= 0);
-
struct sockaddr_in addr;
make_sockaddr(&addr, ip_address);
@@ -120,9 +117,14 @@ int icmp_send_echo_reply(const char *ip_address, int id, int seqnum, const void
msg.checksum = ~compute_checksum(&msg, total_length);
- if (sendto(sock, &msg, ICMP_PAYLOAD_OFFSET + length, 0, (struct sockaddr*)&addr, sizeof addr) < 0) {
- return -1;
- }
+ int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ // The below is only necessary for sending on IPPROTO_RAW sockets
+ // int zero = 0;
+ // assert(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &zero, sizeof zero) >= 0);
+
+ int ret = sendto(sock, &msg, ICMP_PAYLOAD_OFFSET + length, 0, (struct sockaddr*)&addr, sizeof addr);
+ close(sock);
+ if (ret < 0) return -1;
return 0;
}
diff --git a/run_server.sh b/run_server.sh
new file mode 100755
index 0000000..50764b1
--- /dev/null
+++ b/run_server.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+sudo -v
+echo 1 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_all
+sudo ./server
+echo 0 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_all
diff --git a/server.c b/server.c
index 544c59b..db269e5 100644
--- a/server.c
+++ b/server.c
@@ -2,16 +2,12 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
-
-typedef uint8_t u_int8_t;
-typedef uint16_t u_int16_t;
-typedef uint32_t u_int32_t;
-#include <libnetfilter_log/libnetfilter_log.h>
-
+#include <netinet/ip_icmp.h>
#include "icmp.h"
#include "util.h"
@@ -20,7 +16,8 @@ struct state {
int socket;
};
-static int icmp_callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *ldata, void *state_) {
+#if 0
+static int icmp_callback(struct nflog_data *ldata, void *state_) {
(void)gh; (void)nfmsg;
struct state *state = (struct state*)state_;
@@ -47,53 +44,65 @@ static int icmp_callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, stru
return 0;
}
+#endif
int main(void) {
- struct nflog_handle *h = nflog_open();
- if (!h) {
- perror("nflog_open");
- return 1;
- }
- if (nflog_unbind_pf(h, AF_INET) < 0) {
- perror("nflog_unbind_pf");
- return 1;
- }
- if (nflog_bind_pf(h, AF_INET) < 0) {
- perror("nflog_bind_pf");
- return 1;
- }
-
- struct nflog_g_handle *qh = nflog_bind_group(h, 0);
- if (!qh) {
- fprintf(stderr, "nflog_bind_group: no handle for group 0\n");
- return 1;
- }
-
- if (nflog_set_mode(qh, NFULNL_COPY_PACKET, 0xffff) < 0) {
- fprintf(stderr, "nflog_set_mode: can't set packet copy mode\n");
- return 1;
- }
-
- struct state state;
+ // struct state state;
// state.socket = icmp_open_socket();
// if (state.socket < 0) {
// perror("icmp_open_socket");
// return 1;
// }
- nflog_callback_register(qh, &icmp_callback, &state);
+ int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- int fd = nflog_fd(h);
+ struct icmp_echo msg;
- char buf[4096];
+ char buf[MAX_IP_PACKET_SIZE];
while (true) {
- ssize_t nr = recv(fd, buf, sizeof buf, 0);
+ struct iovec iov1;
+ memset(&iov1, 0, sizeof iov1);
+ iov1.iov_base = buf;
+ iov1.iov_len = sizeof buf;
+
+ struct sockaddr_in addr;
+
+ struct msghdr recv_msghdr;
+ memset(&recv_msghdr, 0, sizeof recv_msghdr);
+ recv_msghdr.msg_name = &addr;
+ recv_msghdr.msg_namelen = sizeof addr;
+ recv_msghdr.msg_iov = &iov1;
+ recv_msghdr.msg_iovlen = 1;
+
+ ssize_t nr = recvmsg(sock, &recv_msghdr, 0);
if (nr < 0) break;
- nflog_handle_packet(h, buf, nr);
- }
+ // buf now contains received data starting at the IP header
+
+ printf("Full packet received:\n");
+ xxd(buf, nr);
- nflog_unbind_group(qh);
- nflog_close(h);
+ struct iphdr *hdr = (struct iphdr*)buf;
+ int hdr_len = hdr->ihl * 4;
+ uint32_t saddr = hdr->saddr;
+
+ struct icmp_echo *msg = (struct icmp_echo*)(buf + hdr_len);
+ int msg_len = nr - hdr_len;
+ printf("Received: type %u code %u id %hu seqnum %hu payload:\n",
+ (unsigned)msg->type, (unsigned)msg->code, msg->id, msg->seqnum);
+ xxd(msg->payload, msg_len - offsetof(struct icmp_echo, payload));
+
+ if (msg->type != ICMP_ECHO) {
+ printf("Not an ICMP_ECHO, ignoring\n");
+ continue;
+ }
+
+ uint8_t *saddr_bytes = (uint8_t*)&saddr;
+ char ip_address[16];
+ sprintf(ip_address, "%u.%u.%u.%u", saddr_bytes[0], saddr_bytes[1], saddr_bytes[2], saddr_bytes[3]);
+ if (icmp_send_echo_reply(ip_address, msg->id, msg->seqnum, "dank je wel", 11) < 0) {
+ perror("icmp_send_echo_reply");
+ }
+ }
}