module: added initial implementation
authorRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 07:14:54 +0000 (10:14 +0300)
committerRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 07:14:54 +0000 (10:14 +0300)
.gitignore
module/Kbuild [new file with mode: 0644]
module/Makefile [new file with mode: 0644]
module/p2psp.c [new file with mode: 0644]
module/test.sh [new file with mode: 0755]

index 0d08507..0c2157c 100644 (file)
@@ -19,3 +19,10 @@ cscope.files
 *.class
 *.jar
 *.pyc
+
+*.ko
+*.cmd
+*.mod
+*.mod.c
+Module.symvers
+modules.order
diff --git a/module/Kbuild b/module/Kbuild
new file mode 100644 (file)
index 0000000..1934d9d
--- /dev/null
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS = -Wall -g
+
+obj-m        = p2psp.o
diff --git a/module/Makefile b/module/Makefile
new file mode 100644 (file)
index 0000000..ab6e95b
--- /dev/null
@@ -0,0 +1,7 @@
+KDIR=/lib/modules/`uname -r`/build
+
+kbuild:
+       make -C $(KDIR) M=`pwd`
+
+clean:
+       make -C $(KDIR) M=`pwd` clean
diff --git a/module/p2psp.c b/module/p2psp.c
new file mode 100644 (file)
index 0000000..a29d930
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Simple UDP implementation
+ *
+ * Răzvan Crainea
+ * Tudor Cazangiu
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/net.h>
+#include <linux/in.h>
+
+MODULE_DESCRIPTION("P2P Swift Protocol");
+MODULE_AUTHOR("Razvan Crainea and Tudor Cazangiu");
+MODULE_LICENSE("GPL");
+
+#define LOG_LEVEL              KERN_ALERT
+#define P2PSP_LOCAL_PORT       60000
+#define P2PSP_REMOTE_PORT1     60001
+#define P2PSP_REMOTE_PORT2     60002
+#define MY_TEST_MESSAGE                "kernelsocket\n"
+
+#define ON                     1
+#define OFF                    0
+#define DEBUG                  ON
+
+#if DEBUG == ON
+#define LOG(s)                                 \
+       do {                                    \
+               printk(KERN_DEBUG s "\n");      \
+       } while (0)
+#else
+#define LOG(s)                                 \
+       do {} while (0)
+#endif
+
+#define print_sock_address(addr)               \
+       do {                                    \
+               printk(LOG_LEVEL "connection established to "   \
+                               NIPQUAD_FMT ":%d\n",            \
+                               NIPQUAD(addr.sin_addr.s_addr),  \
+                               ntohs(addr.sin_port));          \
+       } while (0)
+
+static struct socket *sock;    /* UDP server */
+
+/* send datagram */
+static int p2psp_msgsend(struct socket *s, short port)
+{
+       /* address to send to */
+       struct sockaddr_in raddr = {
+               .sin_family     = AF_INET,
+               .sin_port       = htons(port),
+               .sin_addr       = { htonl(INADDR_LOOPBACK) }
+       };
+       int raddrlen = sizeof(raddr);
+       /* message */
+       struct msghdr msg;
+       struct iovec iov;
+       char *buffer = MY_TEST_MESSAGE;
+       int len = strlen(buffer) + 1;
+
+       /* build message */
+       iov.iov_base = buffer;
+       iov.iov_len = len;
+       msg.msg_name = &raddr;
+       msg.msg_namelen = raddrlen;
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_flags = 0;
+
+       /* send the message down the socket */
+       return kernel_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len);
+}
+
+int __init p2psp_sock_init(void)
+{
+       int err;
+       /* address to bind on */
+       struct sockaddr_in addr = {
+               .sin_family     = AF_INET,
+               .sin_port       = htons(P2PSP_LOCAL_PORT),
+               .sin_addr       = { htonl(INADDR_LOOPBACK) }
+       };
+       int addrlen = sizeof(addr);
+
+       /* create UDP socket */
+       err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+       if (err < 0) {
+               printk(LOG_LEVEL "can't create socket\n");
+               goto out;
+       }
+
+       /* bind socket to loopback on port P2PSP_LOCAL_PORT */
+       err = sock->ops->bind(sock, (struct sockaddr *) &addr, addrlen);
+       if (err < 0) {
+               printk(LOG_LEVEL "can't bind socket\n");
+               goto out_release;
+       }
+
+       /* send first message */
+       err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT1);
+       if (err < 0) {
+               printk(LOG_LEVEL "can't send first message\n");
+               goto out_release;
+       }
+
+       /* send second message */
+       err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT2);
+       if (err < 0) {
+               printk(LOG_LEVEL "can't send second message\n");
+               goto out_release;
+       }
+
+
+       return 0;
+
+out_release:
+       /* cleanup socket */
+       sock_release(sock);
+out:
+       return err;
+}
+
+void __exit p2psp_sock_exit(void)
+{
+       /* cleanup socket */
+       sock_release(sock);
+}
+
+module_init(p2psp_sock_init);
+module_exit(p2psp_sock_exit);
diff --git a/module/test.sh b/module/test.sh
new file mode 100755 (executable)
index 0000000..a26b09e
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+LISTENERS=2
+START_PORT=60001
+
+#use nc.traditional
+echo 2 | update-alternatives --config nc &> /dev/null
+
+#set -x
+
+# listen for UDP packets on localhost, port 60001 (run in background)
+for listener in $(seq $LISTENERS); do
+       netcat -l -u -p $START_PORT &
+       pids="$pids $!"
+       START_PORT=$(($START_PORT + 1))
+done
+
+# wait for netcat to start listening
+sleep 1
+
+# insert module, causing the message to be sent
+insmod p2psp.ko
+
+# remove module
+rmmod p2psp
+
+# kill netcat
+for pid in $pids; do
+       kill $pid &> /dev/null
+done