summaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2018-07-23 15:48:44 +0200
committerTom Smeding <tom.smeding@gmail.com>2018-07-23 15:48:44 +0200
commit5722c47aa3402f1458da9eec332153a454a540b7 (patch)
treef1bfaa8c89dc39c6b9ae0bf7ff54eb524b1468eb /server.c
Initial version
Working ping back and forth with specified data, and data arrives at the other party. Currently, the server uses nflog to get the pings, which: 1. requires iptables settings to work; 2. buffers and collects messages for a second. Both are suboptimal, and I believe raw sockets can improve on this.
Diffstat (limited to 'server.c')
-rw-r--r--server.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/server.c b/server.c
new file mode 100644
index 0000000..544c59b
--- /dev/null
+++ b/server.c
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.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 "icmp.h"
+#include "util.h"
+
+
+struct state {
+ int socket;
+};
+
+static int icmp_callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *ldata, void *state_) {
+ (void)gh; (void)nfmsg;
+
+ struct state *state = (struct state*)state_;
+
+ uint8_t *ip_start; // received packet, starting at the IP buffer
+ int ip_len = nflog_get_payload(ldata, (char**)&ip_start);
+
+ struct iphdr *hdr = (struct iphdr*)ip_start;
+ int hdr_len = hdr->ihl * 4;
+ uint32_t saddr = hdr->saddr;
+
+ struct icmp_echo *msg = (struct icmp_echo*)(ip_start + hdr_len);
+ int msg_len = ip_len - 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));
+
+ 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");
+ }
+
+ return 0;
+}
+
+
+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;
+ // state.socket = icmp_open_socket();
+ // if (state.socket < 0) {
+ // perror("icmp_open_socket");
+ // return 1;
+ // }
+
+ nflog_callback_register(qh, &icmp_callback, &state);
+
+ int fd = nflog_fd(h);
+
+ char buf[4096];
+ while (true) {
+ ssize_t nr = recv(fd, buf, sizeof buf, 0);
+ if (nr < 0) break;
+
+ nflog_handle_packet(h, buf, nr);
+ }
+
+ nflog_unbind_group(qh);
+ nflog_close(h);
+}