summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--iv/orodja/ldmitm/.gitignore1
-rw-r--r--iv/orodja/ldmitm/Makefile17
-rw-r--r--iv/orodja/ldmitm/tcp_times.c117
-rw-r--r--iv/orodja/ldmitm/tcp_times.h27
-rw-r--r--iv/orodja/ldmitm/tcp_times_example.c56
6 files changed, 228 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index ed9caac..777d05d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,13 @@ javac.*.args
*.emergency
*.aux
*.toc
+*.so
+core.*
+*.ko
+*.mod
+*.mod.c
+*.mod.o
+*.o
+*.cmd
+*.symvers
+*.order
diff --git a/iv/orodja/ldmitm/.gitignore b/iv/orodja/ldmitm/.gitignore
new file mode 100644
index 0000000..3ce51cd
--- /dev/null
+++ b/iv/orodja/ldmitm/.gitignore
@@ -0,0 +1 @@
+tcp_times_example
diff --git a/iv/orodja/ldmitm/Makefile b/iv/orodja/ldmitm/Makefile
new file mode 100644
index 0000000..4010899
--- /dev/null
+++ b/iv/orodja/ldmitm/Makefile
@@ -0,0 +1,17 @@
+obj-m += tcp_times.o
+
+all: allmods tcp_times_example ldmitm.so
+
+%.so: %.c
+ cc -shared -fPIC -ldl $< -o $@
+
+%: %.c
+ cc -g -Wall -Wextra -pedantic -Wformat -Wformat-security -o$@ $<
+
+allmods:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+clean:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+ rm ldmitm.so tcp_times_example
+
+.PHONY: allmods clean
diff --git a/iv/orodja/ldmitm/tcp_times.c b/iv/orodja/ldmitm/tcp_times.c
new file mode 100644
index 0000000..0996857
--- /dev/null
+++ b/iv/orodja/ldmitm/tcp_times.c
@@ -0,0 +1,117 @@
+/*
+Prevajanje: make
+Namestitev v jedro: insmod tcp_times.ko
+Uporaba v C:
+#include <stdint.h>
+#include "tcp_times.h"
+int tcp_times = open("/proc/tcp_times", O_RDWR);
+if (tcp_times == -1) {
+ perror("open tcp_times");
+ break;
+}
+int tcpsock = accept(boundsocket, &address, &addrlen);
+struct tcp_times tt = {
+ .fd = tcpsock
+};
+if (ioctl(tcp_times, 0, &tt) == -1) {
+ perror("ioctl tcp_times");
+ break;
+}
+// sedaj so polja v tt populirana
+*/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/net.h>
+#include <linux/tcp.h>
+#include <linux/version.h>
+#include "tcp_times.h"
+#define MIN(a,b) (((a)<(b))?(a):(b))
+MODULE_AUTHOR("Anton Luka Šijanec <anton@sijanec.eu>");
+MODULE_DESCRIPTION("tcp last received tsval, rtt procfs ioctl driver");
+MODULE_LICENSE("");
+static struct proc_dir_entry * ent;
+static long myioctl (struct file * filep, unsigned int cmd, unsigned long arg) {
+ switch(cmd) {
+ case 0:
+ struct tcp_times tt;
+ if (copy_from_user(&tt, (void *) arg, sizeof tt))
+ return -EFAULT;
+ struct fd f = fdget(tt.fd);
+ if (!f.file)
+ return -EBADF;
+ struct socket * sock = sock_from_file(f.file);
+ if (!sock) {
+ fdput(f);
+ return -ENOTSOCK;
+ }
+ if (!(sock->type & SOCK_STREAM)) {
+ fdput(f);
+ return -ENOSTR;
+ }
+ if (!sock->sk) {
+ fdput(f);
+ return -EBADFD;
+ }
+ if (sock->sk->sk_protocol != IPPROTO_TCP) {
+ fdput(f);
+ return -ESOCKTNOSUPPORT;
+ }
+ struct tcp_sock * tp = tcp_sk(sock->sk);
+ tt.ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
+ tt.ts_recent = tp->rx_opt.ts_recent;
+ tt.rcv_tsval = tp->rx_opt.rcv_tsval;
+ tt.rcv_tsecr = tp->rx_opt.rcv_tsecr;
+ tt.saw_tstamp = tp->rx_opt.saw_tstamp;
+ tt.tstamp_ok = tp->rx_opt.tstamp_ok;
+ tt.dsack = tp->rx_opt.dsack;
+ tt.wscale_ok = tp->rx_opt.wscale_ok;
+ tt.sack_ok = tp->rx_opt.sack_ok;
+ tt.smc_ok = tp->rx_opt.smc_ok;
+ tt.snd_wscale = tp->rx_opt.snd_wscale;
+ tt.rcv_wscale = tp->rx_opt.rcv_wscale;
+ tt.advmss = tp->advmss;
+ tt.rttvar_us = tp->rttvar_us;
+ tt.srtt_us = tp->srtt_us;
+ tt.rcv_rtt_est.rtt_us = tp->rcv_rtt_est.rtt_us;
+ tt.rcv_rtt_est.seq = tp->rcv_rtt_est.seq;
+ tt.rcv_rtt_est.time = tp->rcv_rtt_est.time;
+ tt.rtt_us = tp->rack.rtt_us;
+ tt.mdev_max_us = tp->mdev_max_us;
+ fdput(f);
+ if (copy_to_user((void *) arg, &tt, sizeof tt)) {
+ fdput(f);
+ return -EFAULT;
+ }
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
+static const struct file_operations ops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = myioctl,
+};
+#else
+static const struct proc_ops ops = {
+ .proc_ioctl = myioctl,
+};
+#endif
+static int __init custom_init (void) {
+ ent = proc_create("tcp_times", 0666, NULL, &ops);
+ if (!ent) {
+ printk(KERN_INFO "tcp_times failed to create procfs entry.");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "tcp_times kernel module loaded.");
+ return 0;
+}
+static void __exit custom_exit (void) {
+ proc_remove(ent);
+ printk(KERN_INFO "tcp_times kernel module exiting ...");
+}
+module_init(custom_init);
+module_exit(custom_exit);
diff --git a/iv/orodja/ldmitm/tcp_times.h b/iv/orodja/ldmitm/tcp_times.h
new file mode 100644
index 0000000..3368c7b
--- /dev/null
+++ b/iv/orodja/ldmitm/tcp_times.h
@@ -0,0 +1,27 @@
+#define TCP_TIMES_PRINTF_FORMAT "fd: %d, ts_recent_stamp: %d, ts_recent: %u, rcv_tsval: %u, rcv_tsecr: %u, saw_tstamp: %u, tstamp_ok: %u, dsack: %u, wscale_ok: %u, sack_ok: %u, snd_wscale: %u, rcv_wscale: %u, advmss: %u, rttvar_us: %u, srtt_us: %u, rcv_rtt_est.rtt_us: %u, rcv_rtt_est.seq: %u, rcv_rtt_est.time: %lu, rtt_us: %u, mdev_max_us: %u"
+#define TCP_TIMES_PRINTF_VARIABLES(tt) tt fd, tt ts_recent_stamp, tt ts_recent, tt rcv_tsval, tt rcv_tsecr, tt saw_tstamp, tt tstamp_ok, tt dsack, tt wscale_ok, tt sack_ok, tt snd_wscale, tt rcv_wscale, tt advmss, tt rttvar_us, tt srtt_us, tt rcv_rtt_est.rtt_us, tt rcv_rtt_est.seq, tt rcv_rtt_est.time, tt rtt_us, tt mdev_max_us
+struct tcp_times { // Polja so pobrana iz jedra. Glej https://elixir.bootlin.com/linux/v6.11-rc4/source/include/linux/tcp.h#L302
+ int fd;
+ int ts_recent_stamp;/* Time we stored ts_recent (for aging) */
+ uint32_t ts_recent; /* Time stamp to echo next */
+ uint32_t rcv_tsval; /* Time stamp value */
+ uint32_t rcv_tsecr; /* Time stamp echo reply */
+ uint16_t saw_tstamp : 1, /* Saw TIMESTAMP on last packet */
+ tstamp_ok : 1, /* TIMESTAMP seen on SYN packet */
+ dsack : 1, /* D-SACK is scheduled */
+ wscale_ok : 1, /* Wscale seen on SYN packet */
+ sack_ok : 3, /* SACK seen on SYN packet */
+ smc_ok : 1, /* SMC seen on SYN packet */
+ snd_wscale : 4, /* Window scaling received from sender */
+ rcv_wscale : 4; /* Window scaling to send to receiver */
+ uint16_t advmss; /* Advertised MSS */
+ uint32_t rttvar_us; /* smoothed mdev_max */
+ uint32_t srtt_us; /* smoothed round trip time << 3 in usecs */
+ struct {
+ uint32_t rtt_us;
+ uint32_t seq;
+ uint64_t time;
+ } rcv_rtt_est;
+ uint32_t rtt_us; /* Associated RTT */
+ uint32_t mdev_max_us; /* maximal mdev for the last rtt period */
+}; // Ne vem, kaj veliko polj tu pomeni, vendar jih dodajam. Mogoče bodo uporabna.
diff --git a/iv/orodja/ldmitm/tcp_times_example.c b/iv/orodja/ldmitm/tcp_times_example.c
new file mode 100644
index 0000000..c98b29a
--- /dev/null
+++ b/iv/orodja/ldmitm/tcp_times_example.c
@@ -0,0 +1,56 @@
+/*
+Posluša na TCP vratih 6969, prejme eno povezavo, vsako sekundo nanjo izpiše LF in piše statistiko, dobljeno iz jedrnega modula tcp_times.
+*/
+#include <stdint.h>
+#include "tcp_times.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+int main (void) {
+ int tcp_socket = socket(AF_INET6, SOCK_STREAM, 0);
+ if (tcp_socket == -1) {
+ perror("socket");
+ return 1;
+ }
+ struct sockaddr_in6 sa6 = {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(6969),
+ .sin6_addr = IN6ADDR_ANY_INIT,
+ };
+ if (bind(tcp_socket, (struct sockaddr *) &sa6, sizeof sa6) == -1) {
+ perror("bind");
+ return 1;
+ }
+ if (listen(tcp_socket, 1 /* only one client is handled*/) == -1) {
+ perror("listen");
+ return 1;
+ }
+ int flow = accept(tcp_socket, NULL, NULL);
+ if (flow == -1) {
+ perror("accept");
+ return 1;
+ }
+ int tcp_times = open("/proc/tcp_times", O_RDWR);
+ struct tcp_times tt = {
+ .fd = flow,
+ };
+ char buf = '\n';
+ while (true) {
+ if (ioctl(tcp_times, 0, &tt) == -1) {
+ perror("ioctl");
+ return 1;
+ }
+ printf(TCP_TIMES_PRINTF_FORMAT "\n", TCP_TIMES_PRINTF_VARIABLES(tt.));
+ if (send(flow, &buf, 1, MSG_NOSIGNAL) == -1) {
+ perror("write");
+ return 1;
+ }
+ sleep(1);
+ }
+}