diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2018-07-23 16:23:56 +0200 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2018-07-25 18:07:49 +0200 |
commit | b582cce69853d0a562dd0171914426887e854966 (patch) | |
tree | 9b5a1c13eb766b8ab4d406d62fa84ec5303e2b46 | |
parent | 5722c47aa3402f1458da9eec332153a454a540b7 (diff) |
Use raw sockets for server
No more buffering, but auto-reply needs to be turned
off; see run_server.sh.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | client.c | 2 | ||||
-rw-r--r-- | icmp.c | 16 | ||||
-rwxr-xr-x | run_server.sh | 5 | ||||
-rw-r--r-- | server.c | 91 |
5 files changed, 66 insertions, 50 deletions
@@ -15,7 +15,7 @@ clean: server: server.o $(OBJECTS) - $(CC) $(CFLAGS) $^ -o $@ -lnetfilter_log + $(CC) $(CFLAGS) $^ -o $@ client: client.o $(OBJECTS) $(CC) $(CFLAGS) $^ -o $@ @@ -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); } @@ -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 @@ -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"); + } + } } |