diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2018-07-23 15:48:44 +0200 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2018-07-23 15:48:44 +0200 |
commit | 5722c47aa3402f1458da9eec332153a454a540b7 (patch) | |
tree | f1bfaa8c89dc39c6b9ae0bf7ff54eb524b1468eb /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.c | 99 |
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); +} |