From 4bf0ec2c5b5a0d106fad48ee3a30d40b2e0e62b7 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 04:49:18 +0000 Subject: [PATCH 01/63] Update ksocket.c --- src/ksocket.c | 437 +++++++++++++++++--------------------------------- 1 file changed, 146 insertions(+), 291 deletions(-) diff --git a/src/ksocket.c b/src/ksocket.c index 1a4f74f..2b1ed6d 100644 --- a/src/ksocket.c +++ b/src/ksocket.c @@ -11,77 +11,50 @@ * @2017 * Hardik Bagdi (hbagdi1@binghamton.edu) * Changes for Compatibility with Linux 4.9 to use iov_iter - * + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. */ #include #include #include +#include #include #include #include #include #include +#include #include "ksocket.h" -//#include "nested.h" -//#include "sxgdebug.h" #define KSOCKET_NAME "ksocket" -#define KSOCKET_VERSION "0.0.2" -#define KSOCKET_DESCPT "BSD-style socket APIs for kernel 2.6 developers" -#define KSOCKET_AUTHOR "msn : song.xian-guang@hotmail.com\n"\ - "blog: http://sxg.cublog.cn" -#define KSOCKET_DATE "2008-05-15" +#define KSOCKET_VERSION "0.0.3" +#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" +#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ + "blog: https://myresume.sh" +#define KSOCKET_DATE "2025-08-03" MODULE_AUTHOR(KSOCKET_AUTHOR); MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); MODULE_LICENSE("Dual BSD/GPL"); -/* -static void (*origSk)(struct sock *sk, int bytes) = NULL; - -static void yh_sk_data_ready(struct sock *sk, int bytes) -{ - if (origSk) { - (*origSk)(sk, bytes); - } - - wake_up_rcv(); - return; -} -*/ - -ksocket_t ksocket(int domain, int type, int protocol) -{ +ksocket_t ksocket(int domain, int type, int protocol) { struct socket *sk = NULL; int ret = 0; ret = sock_create(domain, type, protocol, &sk); - if (ret < 0) - { + if (ret < 0) { printk(KERN_INFO "sock_create failed\n"); return NULL; } - /* - if (sk && sk->sk) { - if (sk->sk->sk_data_ready) { - origSk = sk->sk->sk_data_ready; - sk->sk->sk_data_ready = yh_sk_data_ready; - } else { - printk(KERN_INFO "sk->sk->sk_data_ready is NULL\n"); - } - } else { - printk(KERN_INFO "sk or sk->sk is NULL\n"); - } - */ - printk("sock_create sk= 0x%p\n", sk); return sk; } -int kbind(ksocket_t socket, struct sockaddr *address, int address_len) -{ +int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { struct socket *sk; int ret = 0; @@ -92,23 +65,22 @@ int kbind(ksocket_t socket, struct sockaddr *address, int address_len) return ret; } -int klisten(ksocket_t socket, int backlog) -{ +int klisten(ksocket_t socket, int backlog) { struct socket *sk; int ret; sk = (struct socket *)socket; - if ((unsigned)backlog > SOMAXCONN) + if ((unsigned)backlog > SOMAXCONN) { backlog = SOMAXCONN; + } ret = sk->ops->listen(sk, backlog); return ret; } -int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) -{ +int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { struct socket *sk; int ret; @@ -118,8 +90,7 @@ int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) return ret; } -ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) -{ +ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { struct socket *sk; struct socket *new_sk = NULL; int ret; @@ -131,24 +102,28 @@ ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) //new_sk = sock_alloc(); //sock_alloc() is not exported, so i use sock_create() instead ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); - if (ret < 0) + if (ret < 0) { return NULL; - if (!new_sk) + } + if (!new_sk) { return NULL; + } new_sk->type = sk->type; new_sk->ops = sk->ops; ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); - if (ret < 0) + if (ret < 0) { goto error_kaccept; - - if (address) - { - ret = new_sk->ops->getname(new_sk, address, address_len, 2); - if (ret < 0) - goto error_kaccept; } + + if (address) { + ret = new_sk->ops->getname(new_sk, address, 1); + if (ret < 0) { + goto error_kaccept; + } + } + return new_sk; @@ -157,304 +132,186 @@ ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) return NULL; } -ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) -{ +ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { struct socket *sk; - struct msghdr msg; - struct iovec iov; + struct msghdr msg = { 0 }; + struct kvec iov; int ret; -#ifndef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; -#endif - memset(&msg,0,sizeof(msg)); sk = (struct socket *)socket; - iov.iov_base = (void *)buffer; - iov.iov_len = (__kernel_size_t)length; - - //type - msg.msg_iter.type = READ; - //address - msg.msg_name = NULL; - msg.msg_namelen = 0; - //msg_iter - msg.msg_iter.iov = &iov; - msg.msg_iter.iov_offset = 0; - msg.msg_iter.count = iov.iov_len; - msg.msg_iter.nr_segs = 1; - //control - msg.msg_control = NULL; - msg.msg_controllen = 0; - - /* - * msg.msg_iov->iov_base is declared as follows: - * void __user *iov_base; - * which means there is an user space pointer in 'msg' - * use set_fs(KERNEL_DS) to make the pointer safe to kernel space - */ -#ifndef KSOCKET_ADDR_SAFE - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - //hardik - ret = sock_recvmsg(sk, &msg, flags); -#ifndef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - if (ret < 0) + iov.iov_base = buffer; + iov.iov_len = length; + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + if (ret < 0) { goto out_krecv; - //ret = msg.msg_iov.iov_len;//? - + } + out_krecv: return ret; - } -ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) -{ +ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { struct socket *sk; - struct msghdr msg; - struct iovec iov; + struct msghdr msg = {0}; + struct kvec iov; int len; -#ifndef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; -#endif sk = (struct socket *)socket; iov.iov_base = (void *)buffer; - iov.iov_len = (__kernel_size_t)length; - - //type - msg.msg_iter.type = READ; - //address - msg.msg_name = NULL; - msg.msg_namelen = 0; - //msg_iter - msg.msg_iter.iov = &iov; - msg.msg_iter.iov_offset = 0; - msg.msg_iter.count = iov.iov_len; - msg.msg_iter.nr_segs = 1; - //control - msg.msg_control = NULL; - msg.msg_controllen = 0; - - msg.msg_flags = flags; + iov.iov_len = length; -#ifndef KSOCKET_ADDR_SAFE - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - //hardik - len = sock_sendmsg(sk, &msg);//? -#ifndef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return len;//len ? + len = kernel_sendmsg(sk, &msg, &iov, 1, length); + return len; } -int kshutdown(ksocket_t socket, int how) -{ +int kshutdown(ksocket_t socket, int how) { struct socket *sk; int ret = 0; sk = (struct socket *)socket; - if (sk) + if (sk) { ret = sk->ops->shutdown(sk, how); - + } return ret; } //TODO: ? -int kclose(ksocket_t socket) -{ +int kclose(ksocket_t socket) { struct socket *sk; int ret; sk = (struct socket *)socket; ret = sk->ops->release(sk); - if (sk) + if (sk) { sock_release(sk); - + } return ret; } -ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, - int flags, struct sockaddr * address, - int * address_len) -{ +ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, + int flags, struct sockaddr *address, int *address_len) { struct socket *sk; - struct msghdr msg; - struct iovec iov; - int len; -#ifndef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; -#endif + struct msghdr msg = {0}; + struct kvec iov; + int ret; sk = (struct socket *)socket; - iov.iov_base = (void *)buffer; - iov.iov_len = (__kernel_size_t)length; - - //type - msg.msg_iter.type = READ; - //address - msg.msg_name = address; - msg.msg_namelen = 128; - //msg_iter - msg.msg_iter.iov = &iov; - msg.msg_iter.iov_offset = 0; - msg.msg_iter.count = iov.iov_len; - msg.msg_iter.nr_segs = 1; - //control - msg.msg_control = NULL; - msg.msg_controllen = 0; - -#ifndef KSOCKET_ADDR_SAFE - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - //hardik - len = sock_recvmsg(sk, &msg, flags); -#ifndef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - if (address) - { + // Set up kvec for kernel buffer + iov.iov_base = buffer; + iov.iov_len = length; + + // Set the msg_name and msg_namelen if address is requested + if (address && address_len) { + msg.msg_name = address; + msg.msg_namelen = *address_len; + } + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + + // Update actual received address length + if (ret >= 0 && address_len && msg.msg_namelen > 0) { *address_len = msg.msg_namelen; } - - return len; + return ret; } ssize_t ksendto(ksocket_t socket, void *message, size_t length, - int flags, const struct sockaddr *dest_addr, - int dest_len) -{ - struct socket *sk; - struct msghdr msg; - struct iovec iov; - int len; -#ifndef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; -#endif - - sk = (struct socket *)socket; - - iov.iov_base = (void *)message; - iov.iov_len = (__kernel_size_t)length; + int flags, const struct sockaddr *dest_addr, int dest_len) { + struct socket *sk = (struct socket *)socket; + struct msghdr msg = {0}; + struct kvec iov; + int ret; - //type - msg.msg_iter.type = READ; - //msg_iter - msg.msg_iter.iov = &iov; - msg.msg_iter.iov_offset = 0; - msg.msg_iter.count = iov.iov_len; - msg.msg_iter.nr_segs = 1; - //control - msg.msg_control = NULL; - msg.msg_controllen = 0; + // Set up kvec for kernel-safe buffer + iov.iov_base = message; + iov.iov_len = length; - msg.msg_flags = flags; - if (dest_addr) - { + // Populate destination if provided + if (dest_addr) { msg.msg_name = (void *)dest_addr; msg.msg_namelen = dest_len; } -#ifndef KSOCKET_ADDR_SAFE - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - //hardik - len = sock_sendmsg(sk, &msg);//? -#ifndef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return len;//len ? -} + msg.msg_flags = flags; -int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) -{ - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->getname(sk, address, address_len, 0); - + // Use kernel_sendmsg for modern compatibility + ret = kernel_sendmsg(sk, &msg, &iov, 1, length); return ret; } -int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) -{ - struct socket *sk; +int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; int ret; - - sk = (struct socket *)socket; - ret = sk->ops->getname(sk, address, address_len, 1); - - return ret; + + ret = kernel_getsockname(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) { + *address_len = sizeof(addr); + } + } + + return 0; } -int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) -{ - struct socket *sk; +int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; int ret; -#ifndef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; -#endif - sk = (struct socket *)socket; + ret = kernel_getpeername(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) + *address_len = sizeof(addr); + } -#ifndef KSOCKET_ADDR_SAFE - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif + return 0; +} - if (level == SOL_SOCKET) - ret = sock_setsockopt(sk, level, optname, optval, optlen); - else - ret = sk->ops->setsockopt(sk, level, optname, optval, optlen); +int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { + struct socket *sk = (struct socket *)socket; + sockptr_t opt_ptr; + int ret; -#ifndef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif + // Wrap kernel pointer as a safe sockptr_t + opt_ptr = KERNEL_SOCKPTR(optval); + if (level == SOL_SOCKET) { + ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); + } + else { + ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); + } return ret; } -int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) -{ -/* struct socket *sk; +int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { + struct socket *sk = (struct socket *)socket; int ret; - mm_segment_t old_fs; - sk = (struct socket *)socket; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - if (level == SOL_SOCKET) - ret = sock_getsockopt(sk, level, optname, optval, optlen); - else - ret = sk->ops->getsockopt(sk, level, optname, optval, optlen); - - set_fs(old_fs); + if (!sk || !sk->ops || !sk->ops->getsockopt) { + return -ENOSYS; + } + ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); return ret; -*/ - return -ENOSYS; } - //helper functions -unsigned int inet_addr(char* ip) -{ +unsigned int inet_addr(char* ip) { int a, b, c, d; char addr[4]; @@ -467,29 +324,28 @@ unsigned int inet_addr(char* ip) return *(unsigned int *)addr; } -char *inet_ntoa(struct in_addr *in) -{ +char *inet_ntoa(struct in_addr *in) { char* str_ip = NULL; u_int32_t int_ip = 0; str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); - if (!str_ip) + if (!str_ip) { return NULL; - else + } + else { memset(str_ip, 0, 16); - + } int_ip = in->s_addr; sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, - (int_ip >> 8 ) & 0xFF, - (int_ip >> 16) & 0xFF, - (int_ip >> 24) & 0xFF); + (int_ip >> 8 ) & 0xFF, + (int_ip >> 16) & 0xFF, + (int_ip >> 24) & 0xFF); return str_ip; } //module init and cleanup procedure -static int ksocket_init(void) -{ +static int ksocket_init(void) { printk("%s version %s\n%s\n%s\n", KSOCKET_NAME, KSOCKET_VERSION, KSOCKET_DESCPT, KSOCKET_AUTHOR); @@ -497,8 +353,7 @@ static int ksocket_init(void) return 0; } -static void ksocket_exit(void) -{ +static void ksocket_exit(void) { printk("ksocket exit\n"); } From 75145228d653114a5dfe16ce019b70dc182c68d0 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 04:51:15 +0000 Subject: [PATCH 02/63] Update ksocket.h --- src/ksocket.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ksocket.h b/src/ksocket.h index 42475f3..0528ea0 100644 --- a/src/ksocket.h +++ b/src/ksocket.h @@ -11,8 +11,11 @@ * @2017 * Hardik Bagdi (hbagdi1@binghamton.edu) * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. */ - #ifndef _ksocket_h_ #define _ksocket_h_ From 7d69cef274d03473afb743476888245c8519369e Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 04:58:17 +0000 Subject: [PATCH 03/63] Update Makefile --- src/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile b/src/Makefile index 19d8745..17a6d88 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,8 @@ obj-m += ksocket.o +MARCH=$(gcc -Q -march=native --help=target|grep -m1 march=|awk '{print $2}') +EXTRA_CFLAGS += -Wall -Wextra -Wno-unused-parameter -march=$(MARCH) -pedantic -pipe -O2 + all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: From 9c2b4cc122da16ce33faf9e7ba4c341c8c04c98b Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 05:22:14 +0000 Subject: [PATCH 04/63] Update README.md --- README.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/README.md b/README.md index a15d8fe..fc72643 100644 --- a/README.md +++ b/README.md @@ -14,26 +14,11 @@ $ sudo insmod ksocket.ko #now you can use the exported symbols from this kernel module ``` -### Sample -Look at `sample` sub-directory for code-samples. -``` -$ cd ksocket/sample/tcp/ -$ make -# two kernel modules are ksocket_tcp_cli_demo.ko(TCP client) and ksocket_tcp_srv_demo.ko(TCP server) -$ sudo ksocket_tcp_srv_demo.ko -$ sudo ksocket_tcp_cli_demo.ko -$ dmesg -``` - ### Support across kernel versions The original ksocket work was to support Linux 2.6, however support for v5.4.0 has been included. -v5.4.0 support is a work on Linux ubuntu 5.4.0-66 x86-64, therefore there is no guarantee it works -well on versions > 2.6 && < 5.3.x - -In order to keep the 2.6 version stable it was left without the 5.4.0 work, -instead we now have two branches: v2.6 (master) and v5.4.0 +This version of ksocket was designed for kernels 5.11-6.16. It may work in verions beyond 6.16, but we do not know what future kernel versions will entail. If you need this for an older kernel, see the links below: #### v2.6 original development https://github.com/hbagdi/ksocket From 287692cc6083ec20dda0a0ae487f84b368a752e2 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 05:23:03 +0000 Subject: [PATCH 05/63] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc72643..a287058 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ The ksocket API has been updated to incorporate the changes related to the [iov_ ### Getting started ``` -$ git clone https://github.com/hbagdi/ksocket.git +$ git clone https://github.com/mephistolist/ksocket.git $ cd ksocket/src -$ make # make sure you have the kernel headers/tree installed +$ make # make sure you have the kernel headers/tree installed first $ sudo insmod ksocket.ko #now you can use the exported symbols from this kernel module ``` From 8afbded4a9471a0ac7955e64fd0c9b8202a050c0 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 3 Aug 2025 05:24:01 +0000 Subject: [PATCH 06/63] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a287058..986294b 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,8 @@ $ sudo insmod ksocket.ko ``` ### Support across kernel versions -The original ksocket work was to support Linux 2.6, however support for v5.4.0 has been -included. - -This version of ksocket was designed for kernels 5.11-6.16. It may work in verions beyond 6.16, but we do not know what future kernel versions will entail. If you need this for an older kernel, see the links below: +The original ksocket work was to support Linux 2.6, however support for v5.4.0 was later +included. This version of ksocket was designed for kernels 5.11-6.16. It may work in verions beyond 6.16, but we do not know what future kernel versions will entail. If you need this for an older kernel, see the links below: #### v2.6 original development https://github.com/hbagdi/ksocket From 161400aec0d792d486e59c0b1c3ffdff084e88bb Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:16:21 +0000 Subject: [PATCH 07/63] Update Makefile --- sample/tcp/Makefile | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/sample/tcp/Makefile b/sample/tcp/Makefile index 65989dd..9ccf88d 100644 --- a/sample/tcp/Makefile +++ b/sample/tcp/Makefile @@ -11,23 +11,34 @@ # @2017 # Hardik Bagdi (hbagdi1@binghamton.edu) # Changes for Compatibility with Linux 4.9 to use iov_iter +# +# @2025 +# Mephistolist (cloneozone@gmail.com) +# Updated for kernels 5.11-6.16 +# +KBUILD_EXTRA_SYMBOLS := ../../src/Module.symvers -.PHONY: default clean +obj-m := tcp_server.o -obj-m := ksocket_tcp_srv_demo.o ksocket_tcp_cli_demo.o -#ksocket_tcp_srv-objs := ../ksocket.o -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) -EXTRA_LDFLAGS := -I../../src +EXTRA_CFLAGS += -I$(PWD) -ifeq ($(ADDRSAFE),true) - EXTRA_CFLAGS += -DKSOCKET_ADDR_SAFE -endif +# Name of the userland binary +USER_BINARY := tcp_client +USER_SOURCE := tcp_client.c -default: +default: modules user + +# Build the kernel module +modules: $(MAKE) -C $(KDIR) M=$(PWD) modules -clean: - rm -rf *.ko *.o *.mod.* .H* .tm* .*cmd Module.symvers modules.order +# Build the userland binary +user: + gcc $(USER_SOURCE) -o $(USER_BINARY) +# Clean both kernel module and userland binary +clean: + rm -rf *.o *.ko *.mod.* *.symvers *.order .*cmd $(USER_BINARY) From b53df7a706791c6ab1914681308b7cf25a2ce138 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:16:44 +0000 Subject: [PATCH 08/63] Update Makefile --- sample/tcp/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/sample/tcp/Makefile b/sample/tcp/Makefile index 9ccf88d..8f625d6 100644 --- a/sample/tcp/Makefile +++ b/sample/tcp/Makefile @@ -1,4 +1,3 @@ -# # ksocket project # BSD-style socket APIs for kernel 2.6 developers # From f77b13e55970985dcff0fbbaba81fe5a55855157 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:19:50 +0000 Subject: [PATCH 09/63] Update ksocket.h --- sample/tcp/ksocket.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sample/tcp/ksocket.h b/sample/tcp/ksocket.h index 66368f1..1e306a7 100644 --- a/sample/tcp/ksocket.h +++ b/sample/tcp/ksocket.h @@ -11,8 +11,11 @@ * @2017 * Hardik Bagdi (hbagdi1@binghamton.edu) * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Updated for kernels 5.11-6.16 */ - #ifndef _ksocket_h_ #define _ksocket_h_ From 50230fc695f2c0adc50c75ae9d00e1f14be4975f Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:20:32 +0000 Subject: [PATCH 10/63] Update ksocket.h From 9e59499eb99642cc6911e1a63edb9c872200782f Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:21:49 +0000 Subject: [PATCH 11/63] Create tcp_server.c --- sample/tcp/tcp_server.c | 103 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 sample/tcp/tcp_server.c diff --git a/sample/tcp/tcp_server.c b/sample/tcp/tcp_server.c new file mode 100644 index 0000000..11b3d83 --- /dev/null +++ b/sample/tcp/tcp_server.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +extern unsigned int inet_addr(char *ip); + +static struct task_struct *server_thread; +static ksocket_t sockfd = NULL; // now global so we can access it in exit() + +static int tcp_server_fn(void *data) { + ksocket_t client_sock; + struct sockaddr_in server_addr, client_addr; + int addr_len = sizeof(struct sockaddr_in); + char buf[128]; + int len; + + sockfd = ksocket(AF_INET, SOCK_STREAM, 0); + if (!sockfd) { + printk(KERN_ERR "ksocket: Failed to create TCP socket\n"); + return -1; + } + + int optval = 1; + ksetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons(12345); + + if (kbind(sockfd, (struct sockaddr *)&server_addr, addr_len) < 0) { + printk(KERN_ERR "ksocket: bind failed\n"); + kclose(sockfd); + return -1; + } + + if (klisten(sockfd, 5) < 0) { + printk(KERN_ERR "ksocket: listen failed\n"); + kclose(sockfd); + return -1; + } + + printk(KERN_INFO "ksocket: TCP server listening on port 12345...\n"); + + while (!kthread_should_stop()) { + client_sock = kaccept(sockfd, (struct sockaddr *)&client_addr, &addr_len); + if (!client_sock) { + if (kthread_should_stop()) + break; + + msleep(100); + continue; + } + + memset(buf, 0, sizeof(buf)); + len = krecv(client_sock, buf, sizeof(buf) - 1, 0); + if (len > 0) { + buf[len] = '\0'; + printk(KERN_INFO "ksocket: Received: %s\n", buf); + } + + kclose(client_sock); + } + + if (sockfd) { + kclose(sockfd); + sockfd = NULL; + } + + return 0; +} + +static int __init tcp_server_init(void) { + printk(KERN_INFO "ksocket: Loading TCP server module...\n"); + server_thread = kthread_run(tcp_server_fn, NULL, "tcp_server_thread"); + return 0; +} + +static void __exit tcp_server_exit(void) { + printk(KERN_INFO "ksocket: Unloading TCP server module...\n"); + + if (server_thread) { + if (sockfd) { + kshutdown(sockfd, 2); // SHUT_RDWR: stop reads and writes + } + + kthread_stop(server_thread); + server_thread = NULL; + } +} + +module_init(tcp_server_init); +module_exit(tcp_server_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple TCP Server Example"); +MODULE_AUTHOR("Mephistolist"); From ed955d897189660d56540b82685b1c5385efe10d Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:22:25 +0000 Subject: [PATCH 12/63] Update tcp_server.c --- sample/tcp/tcp_server.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sample/tcp/tcp_server.c b/sample/tcp/tcp_server.c index 11b3d83..727b5f8 100644 --- a/sample/tcp/tcp_server.c +++ b/sample/tcp/tcp_server.c @@ -1,3 +1,21 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Updated for kernels 5.11-6.16 + */ #include #include #include From 638bd23fb76ebf186c5ab1c82283311fa3f5f33c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:23:35 +0000 Subject: [PATCH 13/63] Delete sample/tcp/ksocket_tcp_cli_demo.c --- sample/tcp/ksocket_tcp_cli_demo.c | 92 ------------------------------- 1 file changed, 92 deletions(-) delete mode 100644 sample/tcp/ksocket_tcp_cli_demo.c diff --git a/sample/tcp/ksocket_tcp_cli_demo.c b/sample/tcp/ksocket_tcp_cli_demo.c deleted file mode 100644 index 171b1aa..0000000 --- a/sample/tcp/ksocket_tcp_cli_demo.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ksocket project test sample - tcp client - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ksocket.h" - -#define BUF_SIZE 100 - -int tcp_cli(void *arg) -{ - ksocket_t sockfd_cli; - struct sockaddr_in addr_srv; - char buf[BUF_SIZE], *tmp; - int addr_len; - -#ifdef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - - memset(&addr_srv, 0, sizeof(addr_srv)); - addr_srv.sin_family = AF_INET; - addr_srv.sin_port = htons(4444); - addr_srv.sin_addr.s_addr = inet_addr("127.0.0.1");; - addr_len = sizeof(struct sockaddr_in); - - sockfd_cli = ksocket(AF_INET, SOCK_STREAM, 0); - printk("sockfd_cli = 0x%p\n", sockfd_cli); - if (sockfd_cli == NULL) - { - printk("socket failed\n"); - return -1; - } - if (kconnect(sockfd_cli, (struct sockaddr*)&addr_srv, addr_len) < 0) - { - printk("connect failed\n"); - return -1; - } - - tmp = "quit"; - printk("connected to : %s %d\n", tmp, ntohs(addr_srv.sin_port)); - - krecv(sockfd_cli, buf, 1024, 0); - ksend(sockfd_cli, tmp, 4, 0); - printk("got message : %s\n", buf); - - kclose(sockfd_cli); -#ifdef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return 0; -} - -static int ksocket_tcp_cli_init(void) -{ - kthread_run(tcp_cli,NULL,"tcp_cli_kthread"); - printk("ksocket tcp cli init ok\n"); - return 0; -} - -static void ksocket_tcp_cli_exit(void) -{ - printk("ksocket tcp cli exit\n"); -} - -module_init(ksocket_tcp_cli_init); -module_exit(ksocket_tcp_cli_exit); - -MODULE_LICENSE("Dual BSD/GPL"); From 92b333ef216d7c25b686e922efb785b1b08b270e Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:23:49 +0000 Subject: [PATCH 14/63] Delete sample/tcp/ksocket_tcp_srv_demo.c --- sample/tcp/ksocket_tcp_srv_demo.c | 128 ------------------------------ 1 file changed, 128 deletions(-) delete mode 100644 sample/tcp/ksocket_tcp_srv_demo.c diff --git a/sample/tcp/ksocket_tcp_srv_demo.c b/sample/tcp/ksocket_tcp_srv_demo.c deleted file mode 100644 index 98052df..0000000 --- a/sample/tcp/ksocket_tcp_srv_demo.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ksocket project test sample - tcp server - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ksocket.h" - -#define BUF_SIZE 100 - -static int port = 4444; -module_param(port, int, 0444); - -int tcp_srv(void *arg) -{ - ksocket_t sockfd_srv, sockfd_cli; - struct sockaddr_in addr_srv; - struct sockaddr_in addr_cli; - char buf[BUF_SIZE], *tmp; - int addr_len, len; - -#ifdef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - - sockfd_srv = sockfd_cli = NULL; - memset(&addr_cli, 0, sizeof(addr_cli)); - memset(&addr_srv, 0, sizeof(addr_srv)); - addr_srv.sin_family = AF_INET; - addr_srv.sin_port = htons(port); - addr_srv.sin_addr.s_addr = INADDR_ANY; - addr_len = sizeof(struct sockaddr_in); - - sockfd_srv = ksocket(AF_INET, SOCK_STREAM, 0); - printk("sockfd_srv = 0x%p\n", sockfd_srv); - if (sockfd_srv == NULL) - { - printk("socket failed\n"); - return -1; - } - if (kbind(sockfd_srv, (struct sockaddr *)&addr_srv, addr_len) < 0) - { - printk("bind failed\n"); - return -1; - } - - if (klisten(sockfd_srv, 10) < 0) - { - printk("listen failed\n"); - return -1; - } - - sockfd_cli = kaccept(sockfd_srv, (struct sockaddr *)&addr_cli, &addr_len); - if (sockfd_cli == NULL) - { - printk("accept failed\n"); - return -1; - } - else - printk("sockfd_cli = 0x%p\n", sockfd_cli); - - tmp = inet_ntoa(&addr_cli.sin_addr); - printk("got connected from : %s %d\n", tmp, ntohs(addr_cli.sin_port)); - kfree(tmp); - - len = sprintf(buf, "%s", "Hello, welcome to ksocket tcp srv service\n"); - ksend(sockfd_cli, buf, len, 0); - - while (1) - { - memset(buf, 0, sizeof(buf)); - len = krecv(sockfd_cli, buf, sizeof(buf), 0); - if (len > 0) - { - printk("got message : %s\n", buf); - ksend(sockfd_cli, buf, len, 0); - if (memcmp(buf, "quit", 4) == 0) - break; - } - } - - kclose(sockfd_cli); - kclose(sockfd_srv); -#ifdef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return 0; -} - -static int ksocket_tcp_srv_init(void) -{ - kthread_run(tcp_srv, NULL, "tcp_srv_kthread"); - - printk("ksocket tcp srv init ok\n"); - return 0; -} - -static void ksocket_tcp_srv_exit(void) -{ - printk("ksocket tcp srv exit\n"); -} - -module_init(ksocket_tcp_srv_init); -module_exit(ksocket_tcp_srv_exit); - -MODULE_LICENSE("Dual BSD/GPL"); From 84aaa39c1cef176f8e348c6727a248fb5ec5fabc Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:24:35 +0000 Subject: [PATCH 15/63] Create tcp_client.c --- sample/tcp/tcp_client.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 sample/tcp/tcp_client.c diff --git a/sample/tcp/tcp_client.c b/sample/tcp/tcp_client.c new file mode 100644 index 0000000..13142fb --- /dev/null +++ b/sample/tcp/tcp_client.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + const char *ip = argc > 1 ? argv[1] : "127.0.0.1"; + int port = argc > 2 ? atoi(argv[2]) : 12345; + int sock = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in serv = {0}; + + serv.sin_family = AF_INET; + serv.sin_port = htons(port); + inet_pton(AF_INET, ip, &serv.sin_addr); + + if (connect(sock, (struct sockaddr*)&serv, sizeof(serv)) < 0) { + perror("connect"); + return 1; + } + + char *msg = "Hello from user-space TCP client!"; + send(sock, msg, strlen(msg), 0); + printf("Sent message to %s:%d\n", ip, port); + + close(sock); + return 0; +} From b0469f4a2123577c0f1cf712c8cd4313dd9dca10 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 7 Aug 2025 02:25:18 +0000 Subject: [PATCH 16/63] Update tcp_client.c --- sample/tcp/tcp_client.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sample/tcp/tcp_client.c b/sample/tcp/tcp_client.c index 13142fb..f69e941 100644 --- a/sample/tcp/tcp_client.c +++ b/sample/tcp/tcp_client.c @@ -1,3 +1,21 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Updated for kernels 5.11-6.16 + */ #include #include #include From 37ea87125f43a7b15d1869acb7eb7b593973e6f0 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 02:55:18 +0000 Subject: [PATCH 17/63] Create udp_server.c --- sample/udp/udp_server.c | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 sample/udp/udp_server.c diff --git a/sample/udp/udp_server.c b/sample/udp/udp_server.c new file mode 100644 index 0000000..50e93ec --- /dev/null +++ b/sample/udp/udp_server.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +int udp_server_fn(void *data); +static struct task_struct *server_thread; + +int udp_server_fn(void *data) { + struct socket *sock; + struct sockaddr_in addr; + int ret; + char buffer[256]; + + sock = ksocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (!sock) { + printk(KERN_ERR "UDP Server: Failed to create socket\n"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(4444); + + ret = kbind(sock, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + printk(KERN_ERR "UDP Server: Bind failed (%d)\n", ret); + kclose(sock); + return ret; + } + + printk(KERN_INFO "UDP Server: Listening on port 4444\n"); + + while (!kthread_should_stop()) { + struct sockaddr_in src_addr; + int len = sizeof(src_addr); + + memset(buffer, 0, sizeof(buffer)); + ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, 0, + (struct sockaddr *)&src_addr, &len); + if (ret > 0) { + buffer[ret] = '\0'; + printk(KERN_INFO "UDP Server: Received '%s'\n", buffer); + + // Send back acknowledgement + const char *reply = "ACK from UDP Server"; + ksendto(sock, (void *)reply, strlen(reply), 0, + (struct sockaddr *)&src_addr, sizeof(src_addr)); + } + msleep(100); + } + + kclose(sock); + return 0; +} + +static int __init udp_server_init(void) { + server_thread = kthread_run(udp_server_fn, NULL, "udp_server"); + if (IS_ERR(server_thread)) { + printk(KERN_ERR "UDP Server: Failed to create thread\n"); + return PTR_ERR(server_thread); + } + return 0; +} + +static void __exit udp_server_exit(void) { + if (server_thread) + kthread_stop(server_thread); + printk(KERN_INFO "UDP Server: Exited\n"); +} + +module_init(udp_server_init); +module_exit(udp_server_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple UDP Server Example with ACK"); +MODULE_AUTHOR("Mephistolist"); From 536953e5926aeddb130d7a3ba88f56280c94e4ed Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 02:55:49 +0000 Subject: [PATCH 18/63] Delete sample/udp/ksocket_udp_srv_demo.c --- sample/udp/ksocket_udp_srv_demo.c | 105 ------------------------------ 1 file changed, 105 deletions(-) delete mode 100644 sample/udp/ksocket_udp_srv_demo.c diff --git a/sample/udp/ksocket_udp_srv_demo.c b/sample/udp/ksocket_udp_srv_demo.c deleted file mode 100644 index cf6dc95..0000000 --- a/sample/udp/ksocket_udp_srv_demo.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ksocket project test sample - udp server - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ksocket.h" - -#define BUF_SIZE 100 - -static int port = 4444; -module_param(port, int, 0444); - -int udp_srv(void *arg) -{ - ksocket_t sockfd_srv, sockfd_cli; - struct sockaddr_in addr_srv; - struct sockaddr_in addr_cli; - char buf[BUF_SIZE]; - int addr_len, len; - -#ifdef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - - sockfd_srv = sockfd_cli = NULL; - memset(&addr_cli, 0, sizeof(addr_cli)); - memset(&addr_srv, 0, sizeof(addr_srv)); - addr_srv.sin_family = AF_INET; - addr_srv.sin_port = htons(port); - addr_srv.sin_addr.s_addr = INADDR_ANY; - addr_len = sizeof(struct sockaddr_in); - - sockfd_srv = ksocket(AF_INET, SOCK_DGRAM, 0); - printk("sockfd_srv = 0x%p\n", sockfd_srv); - if (sockfd_srv == NULL) - { - printk("socket failed\n"); - return -1; - } - if (kbind(sockfd_srv, (struct sockaddr *)&addr_srv, addr_len) < 0) - { - printk("bind failed\n"); - return -1; - } - - while (1) - { - memset(buf, 0, sizeof(buf)); - len = krecvfrom(sockfd_srv, buf, sizeof(buf), 0,(struct sockaddr*)&addr_cli,&addr_len); - if (len > 0) - { - printk("got message : %s\n", buf); - ksendto(sockfd_srv, buf, len, 0,(struct sockaddr*)&addr_cli,addr_len); - if (memcmp(buf, "quit", 4) == 0) - break; - } - } - - kclose(sockfd_srv); -#ifdef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return 0; -} - -static int ksocket_udp_srv_init(void) -{ - kthread_run(udp_srv, NULL, "tcp_srv_kthread"); - - printk("ksocket udp srv init ok\n"); - return 0; -} - -static void ksocket_udp_srv_exit(void) -{ - printk("ksocket udp srv exit\n"); -} - -module_init(ksocket_udp_srv_init); -module_exit(ksocket_udp_srv_exit); - -MODULE_LICENSE("Dual BSD/GPL"); From 18d6eb79ef0ba4277a2186dad6da777664b74950 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 02:57:12 +0000 Subject: [PATCH 19/63] Delete sample/udp/ksocket_udp_cli_demo.c --- sample/udp/ksocket_udp_cli_demo.c | 83 ------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 sample/udp/ksocket_udp_cli_demo.c diff --git a/sample/udp/ksocket_udp_cli_demo.c b/sample/udp/ksocket_udp_cli_demo.c deleted file mode 100644 index f0632c5..0000000 --- a/sample/udp/ksocket_udp_cli_demo.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ksocket project test sample - udp client - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ksocket.h" - -#define BUF_SIZE 100 - -int udp_cli(void *arg) -{ - ksocket_t sockfd_cli; - struct sockaddr_in addr_srv; - char buf[BUF_SIZE], *tmp; - int addr_len; - -#ifdef KSOCKET_ADDR_SAFE - mm_segment_t old_fs; - old_fs = get_fs(); - set_fs(KERNEL_DS); -#endif - - memset(&addr_srv, 0, sizeof(addr_srv)); - addr_srv.sin_family = AF_INET; - addr_srv.sin_port = htons(4444); - addr_srv.sin_addr.s_addr = inet_addr("127.0.0.1");; - addr_len = sizeof(struct sockaddr_in); - - sockfd_cli = ksocket(AF_INET, SOCK_DGRAM, 0); - printk("sockfd_cli = 0x%p\n", sockfd_cli); - if (sockfd_cli == NULL) - { - printk("socket failed\n"); - return -1; - } - tmp = "quit"; - ksendto(sockfd_cli, tmp, 4, 0,(struct sockaddr*)&addr_srv, sizeof(addr_srv)); - krecvfrom(sockfd_cli, buf, 1024, 0,(struct sockaddr*)&addr_srv, &addr_len); - printk("got message : %s\n", buf); - kclose(sockfd_cli); -#ifdef KSOCKET_ADDR_SAFE - set_fs(old_fs); -#endif - - return 0; -} - -static int ksocket_udp_cli_init(void) -{ - kthread_run(udp_cli,NULL,"tcp_cli_kthread"); - printk("ksocket udp cli init ok\n"); - return 0; -} - -static void ksocket_udp_cli_exit(void) -{ - printk("ksocket udp cli exit\n"); -} - -module_init(ksocket_udp_cli_init); -module_exit(ksocket_udp_cli_exit); - -MODULE_LICENSE("Dual BSD/GPL"); From 1cdef9efa45b29c6b8ef40b692784dbb0545918c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 02:58:02 +0000 Subject: [PATCH 20/63] Create udp_client.c --- sample/udp/udp_client.c | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 sample/udp/udp_client.c diff --git a/sample/udp/udp_client.c b/sample/udp/udp_client.c new file mode 100644 index 0000000..3e3cd4b --- /dev/null +++ b/sample/udp/udp_client.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SERVER_PORT 4444 +#define SERVER_IP "127.0.0.1" +#define TIMEOUT_SEC 2 + +int main() { + int sockfd; + struct sockaddr_in server_addr; + char buffer[256]; + const char *message = "Hello UDP Server"; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(SERVER_PORT); + + if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) { + perror("inet_pton"); + close(sockfd); + exit(EXIT_FAILURE); + } + + if (sendto(sockfd, message, strlen(message), 0, + (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("sendto"); + close(sockfd); + exit(EXIT_FAILURE); + } + + printf("[client] Sent: %s\n", message); + + // Set receive timeout + struct timeval tv; + tv.tv_sec = TIMEOUT_SEC; + tv.tv_usec = 0; + if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt"); + close(sockfd); + exit(EXIT_FAILURE); + } + + socklen_t addr_len = sizeof(server_addr); + int len = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, + (struct sockaddr *)&server_addr, &addr_len); + if (len < 0) { + perror("[client] No response from server (timeout or unreachable)"); + } else { + buffer[len] = '\0'; + printf("[client] Received: %s\n", buffer); + } + + close(sockfd); + return 0; +} From 7a01695577f31a129b27ebc33015347648372d8b Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 02:58:45 +0000 Subject: [PATCH 21/63] Update Makefile --- sample/udp/Makefile | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/sample/udp/Makefile b/sample/udp/Makefile index 811a0a3..c6ae1b7 100644 --- a/sample/udp/Makefile +++ b/sample/udp/Makefile @@ -1,33 +1,14 @@ -# -# ksocket project -# BSD-style socket APIs for kernel 2.6 developers -# -# @2007-2008, China -# @song.xian-guang@hotmail.com (MSN Accounts) -# -# This code is licenced under the GPL -# Feel free to contact me if any questions -# @2017 -# Hardik Bagdi (hbagdi1@binghamton.edu) -# Changes for Compatibility with Linux 4.9 to use iov_iter -# +KBUILD_EXTRA_SYMBOLS := ../../src/Module.symvers -.PHONY: default clean +obj-m := udp_server.o -obj-m := ksocket_udp_srv_demo.o ksocket_udp_cli_demo.o -#ksocket_tcp_srv-objs := ../ksocket.o -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +EXTRA_CFLAGS += -I$(PWD) -EXTRA_LDFLAGS := -I../../src - -ifeq ($(ADDRSAFE),true) - EXTRA_CFLAGS += -DKSOCKET_ADDR_SAFE -endif - -default: +.PHONY: all clean +all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: - rm -rf *.ko *.o *.mod.* .H* .tm* .*cmd Module.symvers modules.order - + $(MAKE) -C $(KDIR) M=$(PWD) clean From 1bb06e41e68243ba96b9ef3305fe7ac5516afa66 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:28:52 +0000 Subject: [PATCH 22/63] Create Makefile --- samples/tcp/server/Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 samples/tcp/server/Makefile diff --git a/samples/tcp/server/Makefile b/samples/tcp/server/Makefile new file mode 100644 index 0000000..930cc94 --- /dev/null +++ b/samples/tcp/server/Makefile @@ -0,0 +1,16 @@ +KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers + +obj-m := tcp_server.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +EXTRA_CFLAGS += -I$(PWD) + +default: modules + +modules: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + rm -rf *.o *.ko *.mod.* *.symvers *.order .*cmd $(USER_BINARY) From 1ec8c3f95c692ee5515ec90a56620211bbab8a8c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:31:23 +0000 Subject: [PATCH 23/63] Create ksocket.h --- samples/tcp/server/ksocket.h | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 samples/tcp/server/ksocket.h diff --git a/samples/tcp/server/ksocket.h b/samples/tcp/server/ksocket.h new file mode 100644 index 0000000..d32fa99 --- /dev/null +++ b/samples/tcp/server/ksocket.h @@ -0,0 +1,50 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. + */ +#ifndef _ksocket_h_ +#define _ksocket_h_ + +struct socket; +struct sockaddr; +struct in_addr; +typedef struct socket * ksocket_t; + +/* BSD socket APIs prototype declaration */ +extern ksocket_t ksocket(int domain, int type, int protocol); +extern int kshutdown(ksocket_t socket, int how); +extern int kclose(ksocket_t socket); + +extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); +extern int klisten(ksocket_t socket, int backlog); +extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); +extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); + +extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); +extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); +extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); +extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); + +extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); +extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); + +extern unsigned int inet_addr(char* ip); +extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ + +#endif /* !_ksocket_h_ */ From 85c248830f48eca68fb91be723050b13c4893a7e Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:32:36 +0000 Subject: [PATCH 24/63] Create tcp_server.c --- samples/tcp/server/tcp_server.c | 134 ++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 samples/tcp/server/tcp_server.c diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c new file mode 100644 index 0000000..e315657 --- /dev/null +++ b/samples/tcp/server/tcp_server.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +static struct task_struct *server_thread; +static ksocket_t sockfd = NULL; /* global so exit can access it */ + +/* TCP server thread function */ +static int tcp_server_fn(void *data) { + ksocket_t client_sock; + struct sockaddr_in server_addr, client_addr; + int addr_len = sizeof(struct sockaddr_in); + char buf[128]; + int len; + + sockfd = ksocket(AF_INET, SOCK_STREAM, 0); + if (IS_ERR(sockfd)) { + long err = PTR_ERR(sockfd); + printk(KERN_ERR "ksocket: ksocket() failed: %ld\n", err); + sockfd = NULL; + return (int)err; + } + + /* allow immediate reuse of the port */ + { + int optval = 1; + ksetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(optval)); + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons(12345); + + if (kbind(sockfd, (struct sockaddr *)&server_addr, addr_len) < 0) { + printk(KERN_ERR "ksocket: bind failed\n"); + kclose(sockfd); + sockfd = NULL; + return -EINVAL; + } + + if (klisten(sockfd, 5) < 0) { + printk(KERN_ERR "ksocket: listen failed\n"); + kclose(sockfd); + sockfd = NULL; + return -EINVAL; + } + + printk(KERN_INFO "ksocket: TCP server listening on port 12345...\n"); + + while (!kthread_should_stop()) { + if (!sockfd) + break; + + client_sock = kaccept(sockfd, (struct sockaddr *)&client_addr, &addr_len); + if (IS_ERR(client_sock)) { + long err = PTR_ERR(client_sock); + /* if interrupted or shutdown, will get -ERESTARTSYS/-EINTR/-ECONNABORTED etc */ + if (kthread_should_stop()) { + break; + } + printk(KERN_DEBUG "ksocket: kaccept() returned err %ld\n", err); + msleep(100); + continue; + } + + memset(buf, 0, sizeof(buf)); + len = krecv(client_sock, buf, sizeof(buf) - 1, 0); + if (len > 0) { + buf[len] = '\0'; + printk(KERN_INFO "ksocket: Received: %s\n", buf); + } + + kclose(client_sock); + } + + /* clean up listen socket if still present */ + if (sockfd) { + kclose(sockfd); + sockfd = NULL; + } + + return 0; +} + +/* module init: start the server thread */ +static int __init tcp_server_init(void) { + printk(KERN_INFO "ksocket: Loading TCP server module...\n"); + + server_thread = kthread_run(tcp_server_fn, NULL, "tcp_server_thread"); + if (IS_ERR(server_thread)) { + printk(KERN_ERR "ksocket: Failed to start server thread\n"); + server_thread = NULL; + return PTR_ERR(server_thread); + } + + return 0; +} + +/* module exit: shutdown socket (to unblock accept) and stop thread */ +static void __exit tcp_server_exit(void) { + printk(KERN_INFO "ksocket: Unloading TCP server module...\n"); + + /* Ask the socket to shutdown so blocking accept/recv is interrupted */ + if (sockfd) { + kshutdown(sockfd, 2); /* SHUT_RDWR */ + } + + /* Stop the thread (waits for it to exit) */ + if (server_thread) { + kthread_stop(server_thread); + server_thread = NULL; + } + + /* If socket wasn't closed by thread, close it here */ + if (sockfd) { + kclose(sockfd); + sockfd = NULL; + } +} + +module_init(tcp_server_init); +module_exit(tcp_server_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple TCP Server Example"); +MODULE_AUTHOR("Mephistolist"); From 2d52844f4cb2379b411d26d9b102bbfac3f17857 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:34:09 +0000 Subject: [PATCH 25/63] Create Makefile --- samples/tcp/client/Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 samples/tcp/client/Makefile diff --git a/samples/tcp/client/Makefile b/samples/tcp/client/Makefile new file mode 100644 index 0000000..c7a4225 --- /dev/null +++ b/samples/tcp/client/Makefile @@ -0,0 +1,16 @@ +KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers + +obj-m := tcp_client.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +EXTRA_CFLAGS += -I$(PWD) + +default: modules + +modules: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + rm -rf *.o *.ko *.mod.* *.symvers *.order .*cmd $(USER_BINARY) From e6cd4d58ee5b99acd463e74f59299c797f9eebcb Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:35:16 +0000 Subject: [PATCH 26/63] Create ksocket.h --- samples/tcp/client/ksocket.h | 379 +++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 samples/tcp/client/ksocket.h diff --git a/samples/tcp/client/ksocket.h b/samples/tcp/client/ksocket.h new file mode 100644 index 0000000..2b1ed6d --- /dev/null +++ b/samples/tcp/client/ksocket.h @@ -0,0 +1,379 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +#define KSOCKET_NAME "ksocket" +#define KSOCKET_VERSION "0.0.3" +#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" +#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ + "blog: https://myresume.sh" +#define KSOCKET_DATE "2025-08-03" + +MODULE_AUTHOR(KSOCKET_AUTHOR); +MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); +MODULE_LICENSE("Dual BSD/GPL"); + +ksocket_t ksocket(int domain, int type, int protocol) { + struct socket *sk = NULL; + int ret = 0; + + ret = sock_create(domain, type, protocol, &sk); + if (ret < 0) { + printk(KERN_INFO "sock_create failed\n"); + return NULL; + } + + printk("sock_create sk= 0x%p\n", sk); + + return sk; +} + +int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + ret = sk->ops->bind(sk, address, address_len); + printk("kbind ret = %d\n", ret); + + return ret; +} + +int klisten(ksocket_t socket, int backlog) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + + if ((unsigned)backlog > SOMAXCONN) { + backlog = SOMAXCONN; + } + + ret = sk->ops->listen(sk, backlog); + + return ret; +} + +int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); + + return ret; +} + +ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct socket *new_sk = NULL; + int ret; + + sk = (struct socket *)socket; + + printk("family = %d, type = %d, protocol = %d\n", + sk->sk->sk_family, sk->type, sk->sk->sk_protocol); + //new_sk = sock_alloc(); + //sock_alloc() is not exported, so i use sock_create() instead + ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); + if (ret < 0) { + return NULL; + } + if (!new_sk) { + return NULL; + } + + new_sk->type = sk->type; + new_sk->ops = sk->ops; + + ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); + if (ret < 0) { + goto error_kaccept; + } + + if (address) { + ret = new_sk->ops->getname(new_sk, address, 1); + if (ret < 0) { + goto error_kaccept; + } + } + + + return new_sk; + +error_kaccept: + sock_release(new_sk); + return NULL; +} + +ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = { 0 }; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + iov.iov_base = buffer; + iov.iov_len = length; + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + if (ret < 0) { + goto out_krecv; + } + +out_krecv: + return ret; +} + +ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int len; + + sk = (struct socket *)socket; + + iov.iov_base = (void *)buffer; + iov.iov_len = length; + + len = kernel_sendmsg(sk, &msg, &iov, 1, length); + return len; +} + +int kshutdown(ksocket_t socket, int how) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + if (sk) { + ret = sk->ops->shutdown(sk, how); + } + return ret; +} + +//TODO: ? +int kclose(ksocket_t socket) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->release(sk); + + if (sk) { + sock_release(sk); + } + return ret; +} + +ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, + int flags, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + // Set up kvec for kernel buffer + iov.iov_base = buffer; + iov.iov_len = length; + + // Set the msg_name and msg_namelen if address is requested + if (address && address_len) { + msg.msg_name = address; + msg.msg_namelen = *address_len; + } + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + + // Update actual received address length + if (ret >= 0 && address_len && msg.msg_namelen > 0) { + *address_len = msg.msg_namelen; + } + return ret; +} + +ssize_t ksendto(ksocket_t socket, void *message, size_t length, + int flags, const struct sockaddr *dest_addr, int dest_len) { + struct socket *sk = (struct socket *)socket; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + // Set up kvec for kernel-safe buffer + iov.iov_base = message; + iov.iov_len = length; + + // Populate destination if provided + if (dest_addr) { + msg.msg_name = (void *)dest_addr; + msg.msg_namelen = dest_len; + } + + msg.msg_flags = flags; + + // Use kernel_sendmsg for modern compatibility + ret = kernel_sendmsg(sk, &msg, &iov, 1, length); + return ret; +} + +int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getsockname(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) { + *address_len = sizeof(addr); + } + } + + return 0; +} + +int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getpeername(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) + *address_len = sizeof(addr); + } + + return 0; +} + +int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { + struct socket *sk = (struct socket *)socket; + sockptr_t opt_ptr; + int ret; + + // Wrap kernel pointer as a safe sockptr_t + opt_ptr = KERNEL_SOCKPTR(optval); + + if (level == SOL_SOCKET) { + ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); + } + else { + ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); + } + return ret; +} + +int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { + struct socket *sk = (struct socket *)socket; + int ret; + + if (!sk || !sk->ops || !sk->ops->getsockopt) { + return -ENOSYS; + } + ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); + + return ret; +} + +//helper functions +unsigned int inet_addr(char* ip) { + int a, b, c, d; + char addr[4]; + + sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); + addr[0] = a; + addr[1] = b; + addr[2] = c; + addr[3] = d; + + return *(unsigned int *)addr; +} + +char *inet_ntoa(struct in_addr *in) { + char* str_ip = NULL; + u_int32_t int_ip = 0; + + str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); + if (!str_ip) { + return NULL; + } + else { + memset(str_ip, 0, 16); + } + int_ip = in->s_addr; + + sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, + (int_ip >> 8 ) & 0xFF, + (int_ip >> 16) & 0xFF, + (int_ip >> 24) & 0xFF); + return str_ip; +} + +//module init and cleanup procedure +static int ksocket_init(void) { + printk("%s version %s\n%s\n%s\n", + KSOCKET_NAME, KSOCKET_VERSION, + KSOCKET_DESCPT, KSOCKET_AUTHOR); + + return 0; +} + +static void ksocket_exit(void) { + printk("ksocket exit\n"); +} + +module_init(ksocket_init); +module_exit(ksocket_exit); + +EXPORT_SYMBOL(ksocket); +EXPORT_SYMBOL(kbind); +EXPORT_SYMBOL(klisten); +EXPORT_SYMBOL(kconnect); +EXPORT_SYMBOL(kaccept); +EXPORT_SYMBOL(krecv); +EXPORT_SYMBOL(ksend); +EXPORT_SYMBOL(kshutdown); +EXPORT_SYMBOL(kclose); +EXPORT_SYMBOL(krecvfrom); +EXPORT_SYMBOL(ksendto); +EXPORT_SYMBOL(kgetsockname); +EXPORT_SYMBOL(kgetpeername); +EXPORT_SYMBOL(ksetsockopt); +EXPORT_SYMBOL(kgetsockopt); +EXPORT_SYMBOL(inet_addr); +EXPORT_SYMBOL(inet_ntoa); From 8ba16f6f0e7d6f6a27e13b2f25f3e14eea512391 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:36:21 +0000 Subject: [PATCH 27/63] Create tcp_client.c --- samples/tcp/client/tcp_client.c | 85 +++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 samples/tcp/client/tcp_client.c diff --git a/samples/tcp/client/tcp_client.c b/samples/tcp/client/tcp_client.c new file mode 100644 index 0000000..5e44803 --- /dev/null +++ b/samples/tcp/client/tcp_client.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +#define DEFAULT_IP "127.0.0.1" +#define DEFAULT_PORT 12345 + +static struct task_struct *client_thread; + +static int tcp_client_fn(void *data) { + struct socket *sock; + struct sockaddr_in server_addr; + char *ip = (char *)data ? (char *)data : DEFAULT_IP; + int port = DEFAULT_PORT; + const char *message = "Hello from kernel TCP client!"; + int ret; + + // Create TCP socket + sock = ksocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (!sock) { + printk(KERN_ERR "[tcp_client] Failed to create socket\n"); + return -ENOMEM; + } + + // Prepare server address + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + server_addr.sin_addr.s_addr = inet_addr(ip); + + // Connect to server + ret = kconnect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)); + if (ret < 0) { + printk(KERN_ERR "[tcp_client] Failed to connect to %s:%d (err=%d)\n", ip, port, ret); + kclose(sock); + return ret; + } + + printk(KERN_INFO "[tcp_client] Connected to %s:%d\n", ip, port); + + // Send message + ret = ksend(sock, (void *)message, strlen(message), 0); + if (ret < 0) { + printk(KERN_ERR "[tcp_client] Failed to send message (err=%d)\n", ret); + kclose(sock); + return ret; + } + + printk(KERN_INFO "[tcp_client] Sent: %s\n", message); + + kclose(sock); + return 0; +} + +static int __init tcp_client_init(void) { + printk(KERN_INFO "[tcp_client] Initializing\n"); + client_thread = kthread_run(tcp_client_fn, NULL, "tcp_client"); + if (IS_ERR(client_thread)) { + printk(KERN_ERR "[tcp_client] Failed to create thread\n"); + return PTR_ERR(client_thread); + } + return 0; +} + +static void __exit tcp_client_exit(void) { + if (client_thread) + kthread_stop(client_thread); + printk(KERN_INFO "[tcp_client] Exited\n"); +} + +module_init(tcp_client_init); +module_exit(tcp_client_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mephistolist"); +MODULE_DESCRIPTION("Simple TCP Client using ksocket"); From 24d4ba961fb9ec281464fc7b1a16caac7135a772 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:38:20 +0000 Subject: [PATCH 28/63] Create Makefile --- samples/udp/server/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 samples/udp/server/Makefile diff --git a/samples/udp/server/Makefile b/samples/udp/server/Makefile new file mode 100644 index 0000000..cf9a8c7 --- /dev/null +++ b/samples/udp/server/Makefile @@ -0,0 +1,14 @@ +KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers + +obj-m := udp_server.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +EXTRA_CFLAGS += -I$(PWD) + +.PHONY: all clean +all: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean From 6844e76d0b2fd77fd2a42d8c5bc64e4a9d372e77 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:38:58 +0000 Subject: [PATCH 29/63] Create ksocket.h --- samples/udp/server/ksocket.h | 379 +++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 samples/udp/server/ksocket.h diff --git a/samples/udp/server/ksocket.h b/samples/udp/server/ksocket.h new file mode 100644 index 0000000..2b1ed6d --- /dev/null +++ b/samples/udp/server/ksocket.h @@ -0,0 +1,379 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +#define KSOCKET_NAME "ksocket" +#define KSOCKET_VERSION "0.0.3" +#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" +#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ + "blog: https://myresume.sh" +#define KSOCKET_DATE "2025-08-03" + +MODULE_AUTHOR(KSOCKET_AUTHOR); +MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); +MODULE_LICENSE("Dual BSD/GPL"); + +ksocket_t ksocket(int domain, int type, int protocol) { + struct socket *sk = NULL; + int ret = 0; + + ret = sock_create(domain, type, protocol, &sk); + if (ret < 0) { + printk(KERN_INFO "sock_create failed\n"); + return NULL; + } + + printk("sock_create sk= 0x%p\n", sk); + + return sk; +} + +int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + ret = sk->ops->bind(sk, address, address_len); + printk("kbind ret = %d\n", ret); + + return ret; +} + +int klisten(ksocket_t socket, int backlog) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + + if ((unsigned)backlog > SOMAXCONN) { + backlog = SOMAXCONN; + } + + ret = sk->ops->listen(sk, backlog); + + return ret; +} + +int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); + + return ret; +} + +ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct socket *new_sk = NULL; + int ret; + + sk = (struct socket *)socket; + + printk("family = %d, type = %d, protocol = %d\n", + sk->sk->sk_family, sk->type, sk->sk->sk_protocol); + //new_sk = sock_alloc(); + //sock_alloc() is not exported, so i use sock_create() instead + ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); + if (ret < 0) { + return NULL; + } + if (!new_sk) { + return NULL; + } + + new_sk->type = sk->type; + new_sk->ops = sk->ops; + + ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); + if (ret < 0) { + goto error_kaccept; + } + + if (address) { + ret = new_sk->ops->getname(new_sk, address, 1); + if (ret < 0) { + goto error_kaccept; + } + } + + + return new_sk; + +error_kaccept: + sock_release(new_sk); + return NULL; +} + +ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = { 0 }; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + iov.iov_base = buffer; + iov.iov_len = length; + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + if (ret < 0) { + goto out_krecv; + } + +out_krecv: + return ret; +} + +ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int len; + + sk = (struct socket *)socket; + + iov.iov_base = (void *)buffer; + iov.iov_len = length; + + len = kernel_sendmsg(sk, &msg, &iov, 1, length); + return len; +} + +int kshutdown(ksocket_t socket, int how) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + if (sk) { + ret = sk->ops->shutdown(sk, how); + } + return ret; +} + +//TODO: ? +int kclose(ksocket_t socket) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->release(sk); + + if (sk) { + sock_release(sk); + } + return ret; +} + +ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, + int flags, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + // Set up kvec for kernel buffer + iov.iov_base = buffer; + iov.iov_len = length; + + // Set the msg_name and msg_namelen if address is requested + if (address && address_len) { + msg.msg_name = address; + msg.msg_namelen = *address_len; + } + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + + // Update actual received address length + if (ret >= 0 && address_len && msg.msg_namelen > 0) { + *address_len = msg.msg_namelen; + } + return ret; +} + +ssize_t ksendto(ksocket_t socket, void *message, size_t length, + int flags, const struct sockaddr *dest_addr, int dest_len) { + struct socket *sk = (struct socket *)socket; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + // Set up kvec for kernel-safe buffer + iov.iov_base = message; + iov.iov_len = length; + + // Populate destination if provided + if (dest_addr) { + msg.msg_name = (void *)dest_addr; + msg.msg_namelen = dest_len; + } + + msg.msg_flags = flags; + + // Use kernel_sendmsg for modern compatibility + ret = kernel_sendmsg(sk, &msg, &iov, 1, length); + return ret; +} + +int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getsockname(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) { + *address_len = sizeof(addr); + } + } + + return 0; +} + +int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getpeername(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) + *address_len = sizeof(addr); + } + + return 0; +} + +int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { + struct socket *sk = (struct socket *)socket; + sockptr_t opt_ptr; + int ret; + + // Wrap kernel pointer as a safe sockptr_t + opt_ptr = KERNEL_SOCKPTR(optval); + + if (level == SOL_SOCKET) { + ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); + } + else { + ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); + } + return ret; +} + +int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { + struct socket *sk = (struct socket *)socket; + int ret; + + if (!sk || !sk->ops || !sk->ops->getsockopt) { + return -ENOSYS; + } + ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); + + return ret; +} + +//helper functions +unsigned int inet_addr(char* ip) { + int a, b, c, d; + char addr[4]; + + sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); + addr[0] = a; + addr[1] = b; + addr[2] = c; + addr[3] = d; + + return *(unsigned int *)addr; +} + +char *inet_ntoa(struct in_addr *in) { + char* str_ip = NULL; + u_int32_t int_ip = 0; + + str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); + if (!str_ip) { + return NULL; + } + else { + memset(str_ip, 0, 16); + } + int_ip = in->s_addr; + + sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, + (int_ip >> 8 ) & 0xFF, + (int_ip >> 16) & 0xFF, + (int_ip >> 24) & 0xFF); + return str_ip; +} + +//module init and cleanup procedure +static int ksocket_init(void) { + printk("%s version %s\n%s\n%s\n", + KSOCKET_NAME, KSOCKET_VERSION, + KSOCKET_DESCPT, KSOCKET_AUTHOR); + + return 0; +} + +static void ksocket_exit(void) { + printk("ksocket exit\n"); +} + +module_init(ksocket_init); +module_exit(ksocket_exit); + +EXPORT_SYMBOL(ksocket); +EXPORT_SYMBOL(kbind); +EXPORT_SYMBOL(klisten); +EXPORT_SYMBOL(kconnect); +EXPORT_SYMBOL(kaccept); +EXPORT_SYMBOL(krecv); +EXPORT_SYMBOL(ksend); +EXPORT_SYMBOL(kshutdown); +EXPORT_SYMBOL(kclose); +EXPORT_SYMBOL(krecvfrom); +EXPORT_SYMBOL(ksendto); +EXPORT_SYMBOL(kgetsockname); +EXPORT_SYMBOL(kgetpeername); +EXPORT_SYMBOL(ksetsockopt); +EXPORT_SYMBOL(kgetsockopt); +EXPORT_SYMBOL(inet_addr); +EXPORT_SYMBOL(inet_ntoa); From f296f1d6cf2f1faae18c1028a7cf07422a94ecc5 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:39:40 +0000 Subject: [PATCH 30/63] Create udp_server.c --- samples/udp/server/udp_server.c | 84 +++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 samples/udp/server/udp_server.c diff --git a/samples/udp/server/udp_server.c b/samples/udp/server/udp_server.c new file mode 100644 index 0000000..50e93ec --- /dev/null +++ b/samples/udp/server/udp_server.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +int udp_server_fn(void *data); +static struct task_struct *server_thread; + +int udp_server_fn(void *data) { + struct socket *sock; + struct sockaddr_in addr; + int ret; + char buffer[256]; + + sock = ksocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (!sock) { + printk(KERN_ERR "UDP Server: Failed to create socket\n"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(4444); + + ret = kbind(sock, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + printk(KERN_ERR "UDP Server: Bind failed (%d)\n", ret); + kclose(sock); + return ret; + } + + printk(KERN_INFO "UDP Server: Listening on port 4444\n"); + + while (!kthread_should_stop()) { + struct sockaddr_in src_addr; + int len = sizeof(src_addr); + + memset(buffer, 0, sizeof(buffer)); + ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, 0, + (struct sockaddr *)&src_addr, &len); + if (ret > 0) { + buffer[ret] = '\0'; + printk(KERN_INFO "UDP Server: Received '%s'\n", buffer); + + // Send back acknowledgement + const char *reply = "ACK from UDP Server"; + ksendto(sock, (void *)reply, strlen(reply), 0, + (struct sockaddr *)&src_addr, sizeof(src_addr)); + } + msleep(100); + } + + kclose(sock); + return 0; +} + +static int __init udp_server_init(void) { + server_thread = kthread_run(udp_server_fn, NULL, "udp_server"); + if (IS_ERR(server_thread)) { + printk(KERN_ERR "UDP Server: Failed to create thread\n"); + return PTR_ERR(server_thread); + } + return 0; +} + +static void __exit udp_server_exit(void) { + if (server_thread) + kthread_stop(server_thread); + printk(KERN_INFO "UDP Server: Exited\n"); +} + +module_init(udp_server_init); +module_exit(udp_server_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple UDP Server Example with ACK"); +MODULE_AUTHOR("Mephistolist"); From 7b0737c39a57e81bab47fdd427c063dd22ac6589 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:42:57 +0000 Subject: [PATCH 31/63] Create Makefile --- samples/udp/client/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 samples/udp/client/Makefile diff --git a/samples/udp/client/Makefile b/samples/udp/client/Makefile new file mode 100644 index 0000000..fddc4d1 --- /dev/null +++ b/samples/udp/client/Makefile @@ -0,0 +1,14 @@ +KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers + +obj-m := udp_client.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +EXTRA_CFLAGS += -I$(PWD) + +.PHONY: all clean +all: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean From edf7f5e7dcaacfb9f511dbf9c0478fa076e0bbcc Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:43:24 +0000 Subject: [PATCH 32/63] Create ksocket.h --- samples/udp/client/ksocket.h | 379 +++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 samples/udp/client/ksocket.h diff --git a/samples/udp/client/ksocket.h b/samples/udp/client/ksocket.h new file mode 100644 index 0000000..2b1ed6d --- /dev/null +++ b/samples/udp/client/ksocket.h @@ -0,0 +1,379 @@ +/* + * ksocket project + * BSD-style socket APIs for kernel 2.6 developers + * + * @2007-2008, China + * @song.xian-guang@hotmail.com (MSN Accounts) + * + * This code is licenced under the GPL + * Feel free to contact me if any questions + * + * @2017 + * Hardik Bagdi (hbagdi1@binghamton.edu) + * Changes for Compatibility with Linux 4.9 to use iov_iter + * + * @2025 + * Mephistolist (cloneozone@gmail.com) + * Changes for kernels 5.11 through at least 6.16. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +#define KSOCKET_NAME "ksocket" +#define KSOCKET_VERSION "0.0.3" +#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" +#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ + "blog: https://myresume.sh" +#define KSOCKET_DATE "2025-08-03" + +MODULE_AUTHOR(KSOCKET_AUTHOR); +MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); +MODULE_LICENSE("Dual BSD/GPL"); + +ksocket_t ksocket(int domain, int type, int protocol) { + struct socket *sk = NULL; + int ret = 0; + + ret = sock_create(domain, type, protocol, &sk); + if (ret < 0) { + printk(KERN_INFO "sock_create failed\n"); + return NULL; + } + + printk("sock_create sk= 0x%p\n", sk); + + return sk; +} + +int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + ret = sk->ops->bind(sk, address, address_len); + printk("kbind ret = %d\n", ret); + + return ret; +} + +int klisten(ksocket_t socket, int backlog) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + + if ((unsigned)backlog > SOMAXCONN) { + backlog = SOMAXCONN; + } + + ret = sk->ops->listen(sk, backlog); + + return ret; +} + +int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); + + return ret; +} + +ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct socket *new_sk = NULL; + int ret; + + sk = (struct socket *)socket; + + printk("family = %d, type = %d, protocol = %d\n", + sk->sk->sk_family, sk->type, sk->sk->sk_protocol); + //new_sk = sock_alloc(); + //sock_alloc() is not exported, so i use sock_create() instead + ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); + if (ret < 0) { + return NULL; + } + if (!new_sk) { + return NULL; + } + + new_sk->type = sk->type; + new_sk->ops = sk->ops; + + ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); + if (ret < 0) { + goto error_kaccept; + } + + if (address) { + ret = new_sk->ops->getname(new_sk, address, 1); + if (ret < 0) { + goto error_kaccept; + } + } + + + return new_sk; + +error_kaccept: + sock_release(new_sk); + return NULL; +} + +ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = { 0 }; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + iov.iov_base = buffer; + iov.iov_len = length; + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + if (ret < 0) { + goto out_krecv; + } + +out_krecv: + return ret; +} + +ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int len; + + sk = (struct socket *)socket; + + iov.iov_base = (void *)buffer; + iov.iov_len = length; + + len = kernel_sendmsg(sk, &msg, &iov, 1, length); + return len; +} + +int kshutdown(ksocket_t socket, int how) { + struct socket *sk; + int ret = 0; + + sk = (struct socket *)socket; + if (sk) { + ret = sk->ops->shutdown(sk, how); + } + return ret; +} + +//TODO: ? +int kclose(ksocket_t socket) { + struct socket *sk; + int ret; + + sk = (struct socket *)socket; + ret = sk->ops->release(sk); + + if (sk) { + sock_release(sk); + } + return ret; +} + +ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, + int flags, struct sockaddr *address, int *address_len) { + struct socket *sk; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + sk = (struct socket *)socket; + + // Set up kvec for kernel buffer + iov.iov_base = buffer; + iov.iov_len = length; + + // Set the msg_name and msg_namelen if address is requested + if (address && address_len) { + msg.msg_name = address; + msg.msg_namelen = *address_len; + } + + ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); + + // Update actual received address length + if (ret >= 0 && address_len && msg.msg_namelen > 0) { + *address_len = msg.msg_namelen; + } + return ret; +} + +ssize_t ksendto(ksocket_t socket, void *message, size_t length, + int flags, const struct sockaddr *dest_addr, int dest_len) { + struct socket *sk = (struct socket *)socket; + struct msghdr msg = {0}; + struct kvec iov; + int ret; + + // Set up kvec for kernel-safe buffer + iov.iov_base = message; + iov.iov_len = length; + + // Populate destination if provided + if (dest_addr) { + msg.msg_name = (void *)dest_addr; + msg.msg_namelen = dest_len; + } + + msg.msg_flags = flags; + + // Use kernel_sendmsg for modern compatibility + ret = kernel_sendmsg(sk, &msg, &iov, 1, length); + return ret; +} + +int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getsockname(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) { + *address_len = sizeof(addr); + } + } + + return 0; +} + +int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { + struct socket *sk = (struct socket *)socket; + struct sockaddr_storage addr; + int ret; + + ret = kernel_getpeername(sk, (struct sockaddr *)&addr); + if (ret < 0) { + return ret; + } + if (address) { + memcpy(address, &addr, sizeof(addr)); + if (address_len) + *address_len = sizeof(addr); + } + + return 0; +} + +int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { + struct socket *sk = (struct socket *)socket; + sockptr_t opt_ptr; + int ret; + + // Wrap kernel pointer as a safe sockptr_t + opt_ptr = KERNEL_SOCKPTR(optval); + + if (level == SOL_SOCKET) { + ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); + } + else { + ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); + } + return ret; +} + +int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { + struct socket *sk = (struct socket *)socket; + int ret; + + if (!sk || !sk->ops || !sk->ops->getsockopt) { + return -ENOSYS; + } + ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); + + return ret; +} + +//helper functions +unsigned int inet_addr(char* ip) { + int a, b, c, d; + char addr[4]; + + sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); + addr[0] = a; + addr[1] = b; + addr[2] = c; + addr[3] = d; + + return *(unsigned int *)addr; +} + +char *inet_ntoa(struct in_addr *in) { + char* str_ip = NULL; + u_int32_t int_ip = 0; + + str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); + if (!str_ip) { + return NULL; + } + else { + memset(str_ip, 0, 16); + } + int_ip = in->s_addr; + + sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, + (int_ip >> 8 ) & 0xFF, + (int_ip >> 16) & 0xFF, + (int_ip >> 24) & 0xFF); + return str_ip; +} + +//module init and cleanup procedure +static int ksocket_init(void) { + printk("%s version %s\n%s\n%s\n", + KSOCKET_NAME, KSOCKET_VERSION, + KSOCKET_DESCPT, KSOCKET_AUTHOR); + + return 0; +} + +static void ksocket_exit(void) { + printk("ksocket exit\n"); +} + +module_init(ksocket_init); +module_exit(ksocket_exit); + +EXPORT_SYMBOL(ksocket); +EXPORT_SYMBOL(kbind); +EXPORT_SYMBOL(klisten); +EXPORT_SYMBOL(kconnect); +EXPORT_SYMBOL(kaccept); +EXPORT_SYMBOL(krecv); +EXPORT_SYMBOL(ksend); +EXPORT_SYMBOL(kshutdown); +EXPORT_SYMBOL(kclose); +EXPORT_SYMBOL(krecvfrom); +EXPORT_SYMBOL(ksendto); +EXPORT_SYMBOL(kgetsockname); +EXPORT_SYMBOL(kgetpeername); +EXPORT_SYMBOL(ksetsockopt); +EXPORT_SYMBOL(kgetsockopt); +EXPORT_SYMBOL(inet_addr); +EXPORT_SYMBOL(inet_ntoa); From ba17592231a0f17daf8a8ded191fa42cb47a2405 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:44:28 +0000 Subject: [PATCH 33/63] Create udp_client.c --- samples/udp/client/udp_client.c | 97 +++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 samples/udp/client/udp_client.c diff --git a/samples/udp/client/udp_client.c b/samples/udp/client/udp_client.c new file mode 100644 index 0000000..c3c849f --- /dev/null +++ b/samples/udp/client/udp_client.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ksocket.h" + +#define SERVER_PORT 4444 +#define SERVER_IP "127.0.0.1" +#define TIMEOUT_MS 2000 // 2 seconds + +static struct task_struct *client_thread; + +static int udp_client_fn(void *data) { + struct socket *sock; + struct sockaddr_in server_addr; + char buffer[256]; + const char *message = "Hello UDP Server"; + int ret; + + sock = ksocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (!sock) { + printk(KERN_ERR "[udp_client] Failed to create socket\n"); + return -ENOMEM; + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(SERVER_PORT); + server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); + + // Send message + ret = ksendto(sock, (void *)message, strlen(message), 0, + (struct sockaddr *)&server_addr, sizeof(server_addr)); + if (ret < 0) { + printk(KERN_ERR "[udp_client] Failed to send message (%d)\n", ret); + kclose(sock); + return ret; + } + + printk(KERN_INFO "[udp_client] Sent: %s\n", message); + + // Non-blocking receive with timeout + { + unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); + int addr_len = sizeof(server_addr); + ret = -EAGAIN; + + while (time_before(jiffies, timeout)) { + ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, MSG_DONTWAIT, + (struct sockaddr *)&server_addr, &addr_len); + if (ret >= 0) { + buffer[ret] = '\0'; + printk(KERN_INFO "[udp_client] Received: %s\n", buffer); + break; + } + msleep(50); + } + + if (ret < 0) + printk(KERN_WARNING "[udp_client] No response from server (timeout or unreachable)\n"); + } + + kclose(sock); + return 0; +} + +static int __init udp_client_init(void) { + printk(KERN_INFO "[udp_client] Initializing\n"); + client_thread = kthread_run(udp_client_fn, NULL, "udp_client"); + if (IS_ERR(client_thread)) { + printk(KERN_ERR "[udp_client] Failed to create thread\n"); + return PTR_ERR(client_thread); + } + return 0; +} + +static void __exit udp_client_exit(void) { + if (client_thread) + kthread_stop(client_thread); + printk(KERN_INFO "[udp_client] Exited\n"); +} + +module_init(udp_client_init); +module_exit(udp_client_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mephistolist"); +MODULE_DESCRIPTION("Simple UDP Client using ksocket"); From 8011e009fa78191a91a8f5c2ab929f3d345d04ea Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:45:34 +0000 Subject: [PATCH 34/63] Delete sample/tcp directory --- sample/tcp/Makefile | 43 -------------- sample/tcp/ksocket.h | 50 ----------------- sample/tcp/tcp_client.c | 46 --------------- sample/tcp/tcp_server.c | 121 ---------------------------------------- 4 files changed, 260 deletions(-) delete mode 100644 sample/tcp/Makefile delete mode 100644 sample/tcp/ksocket.h delete mode 100644 sample/tcp/tcp_client.c delete mode 100644 sample/tcp/tcp_server.c diff --git a/sample/tcp/Makefile b/sample/tcp/Makefile deleted file mode 100644 index 8f625d6..0000000 --- a/sample/tcp/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# ksocket project -# BSD-style socket APIs for kernel 2.6 developers -# -# @2007-2008, China -# @song.xian-guang@hotmail.com (MSN Accounts) -# -# This code is licenced under the GPL -# Feel free to contact me if any questions -# -# @2017 -# Hardik Bagdi (hbagdi1@binghamton.edu) -# Changes for Compatibility with Linux 4.9 to use iov_iter -# -# @2025 -# Mephistolist (cloneozone@gmail.com) -# Updated for kernels 5.11-6.16 -# -KBUILD_EXTRA_SYMBOLS := ../../src/Module.symvers - -obj-m := tcp_server.o - -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -EXTRA_CFLAGS += -I$(PWD) - -# Name of the userland binary -USER_BINARY := tcp_client -USER_SOURCE := tcp_client.c - -default: modules user - -# Build the kernel module -modules: - $(MAKE) -C $(KDIR) M=$(PWD) modules - -# Build the userland binary -user: - gcc $(USER_SOURCE) -o $(USER_BINARY) - -# Clean both kernel module and userland binary -clean: - rm -rf *.o *.ko *.mod.* *.symvers *.order .*cmd $(USER_BINARY) diff --git a/sample/tcp/ksocket.h b/sample/tcp/ksocket.h deleted file mode 100644 index 1e306a7..0000000 --- a/sample/tcp/ksocket.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ksocket project - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - * - * @2025 - * Mephistolist (cloneozone@gmail.com) - * Updated for kernels 5.11-6.16 - */ -#ifndef _ksocket_h_ -#define _ksocket_h_ - -struct socket; -struct sockaddr; -struct in_addr; -typedef struct socket * ksocket_t; - -/* BSD socket APIs prototype declaration */ -extern ksocket_t ksocket(int domain, int type, int protocol); -extern int kshutdown(ksocket_t socket, int how); -extern int kclose(ksocket_t socket); - -extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); -extern int klisten(ksocket_t socket, int backlog); -extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); -extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); - -extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); -extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); -extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); -extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); - -extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); -extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); -extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); -extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); - -extern unsigned int inet_addr(char* ip); -extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ - -#endif /* !_ksocket_h_ */ diff --git a/sample/tcp/tcp_client.c b/sample/tcp/tcp_client.c deleted file mode 100644 index f69e941..0000000 --- a/sample/tcp/tcp_client.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ksocket project - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - * - * @2025 - * Mephistolist (cloneozone@gmail.com) - * Updated for kernels 5.11-6.16 - */ -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - const char *ip = argc > 1 ? argv[1] : "127.0.0.1"; - int port = argc > 2 ? atoi(argv[2]) : 12345; - int sock = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in serv = {0}; - - serv.sin_family = AF_INET; - serv.sin_port = htons(port); - inet_pton(AF_INET, ip, &serv.sin_addr); - - if (connect(sock, (struct sockaddr*)&serv, sizeof(serv)) < 0) { - perror("connect"); - return 1; - } - - char *msg = "Hello from user-space TCP client!"; - send(sock, msg, strlen(msg), 0); - printf("Sent message to %s:%d\n", ip, port); - - close(sock); - return 0; -} diff --git a/sample/tcp/tcp_server.c b/sample/tcp/tcp_server.c deleted file mode 100644 index 727b5f8..0000000 --- a/sample/tcp/tcp_server.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * ksocket project - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - * - * @2025 - * Mephistolist (cloneozone@gmail.com) - * Updated for kernels 5.11-6.16 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ksocket.h" - -extern unsigned int inet_addr(char *ip); - -static struct task_struct *server_thread; -static ksocket_t sockfd = NULL; // now global so we can access it in exit() - -static int tcp_server_fn(void *data) { - ksocket_t client_sock; - struct sockaddr_in server_addr, client_addr; - int addr_len = sizeof(struct sockaddr_in); - char buf[128]; - int len; - - sockfd = ksocket(AF_INET, SOCK_STREAM, 0); - if (!sockfd) { - printk(KERN_ERR "ksocket: Failed to create TCP socket\n"); - return -1; - } - - int optval = 1; - ksetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); - - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htonl(INADDR_ANY); - server_addr.sin_port = htons(12345); - - if (kbind(sockfd, (struct sockaddr *)&server_addr, addr_len) < 0) { - printk(KERN_ERR "ksocket: bind failed\n"); - kclose(sockfd); - return -1; - } - - if (klisten(sockfd, 5) < 0) { - printk(KERN_ERR "ksocket: listen failed\n"); - kclose(sockfd); - return -1; - } - - printk(KERN_INFO "ksocket: TCP server listening on port 12345...\n"); - - while (!kthread_should_stop()) { - client_sock = kaccept(sockfd, (struct sockaddr *)&client_addr, &addr_len); - if (!client_sock) { - if (kthread_should_stop()) - break; - - msleep(100); - continue; - } - - memset(buf, 0, sizeof(buf)); - len = krecv(client_sock, buf, sizeof(buf) - 1, 0); - if (len > 0) { - buf[len] = '\0'; - printk(KERN_INFO "ksocket: Received: %s\n", buf); - } - - kclose(client_sock); - } - - if (sockfd) { - kclose(sockfd); - sockfd = NULL; - } - - return 0; -} - -static int __init tcp_server_init(void) { - printk(KERN_INFO "ksocket: Loading TCP server module...\n"); - server_thread = kthread_run(tcp_server_fn, NULL, "tcp_server_thread"); - return 0; -} - -static void __exit tcp_server_exit(void) { - printk(KERN_INFO "ksocket: Unloading TCP server module...\n"); - - if (server_thread) { - if (sockfd) { - kshutdown(sockfd, 2); // SHUT_RDWR: stop reads and writes - } - - kthread_stop(server_thread); - server_thread = NULL; - } -} - -module_init(tcp_server_init); -module_exit(tcp_server_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Simple TCP Server Example"); -MODULE_AUTHOR("Mephistolist"); From 7a56b0bd3a4bf191aece495ac774a1d1389dfd2a Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:45:46 +0000 Subject: [PATCH 35/63] Delete sample/udp directory --- sample/udp/Makefile | 14 ------- sample/udp/ksocket.h | 48 ----------------------- sample/udp/udp_client.c | 66 -------------------------------- sample/udp/udp_server.c | 84 ----------------------------------------- 4 files changed, 212 deletions(-) delete mode 100644 sample/udp/Makefile delete mode 100644 sample/udp/ksocket.h delete mode 100644 sample/udp/udp_client.c delete mode 100644 sample/udp/udp_server.c diff --git a/sample/udp/Makefile b/sample/udp/Makefile deleted file mode 100644 index c6ae1b7..0000000 --- a/sample/udp/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -KBUILD_EXTRA_SYMBOLS := ../../src/Module.symvers - -obj-m := udp_server.o - -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) -EXTRA_CFLAGS += -I$(PWD) - -.PHONY: all clean -all: - $(MAKE) -C $(KDIR) M=$(PWD) modules - -clean: - $(MAKE) -C $(KDIR) M=$(PWD) clean diff --git a/sample/udp/ksocket.h b/sample/udp/ksocket.h deleted file mode 100644 index 9884f5d..0000000 --- a/sample/udp/ksocket.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * ksocket project - * BSD-style socket APIs for kernel 2.6 developers - * - * @2007-2008, China - * @song.xian-guang@hotmail.com (MSN Accounts) - * - * This code is licenced under the GPL - * Feel free to contact me if any questions - * - * @2017 - * Hardik Bagdi (hbagdi1@binghamton.edu) - * Changes for Compatibility with Linux 4.9 to use iov_iter - * - */ - -#ifndef _ksocket_h_ -#define _ksocket_h_ - -struct socket; -struct sockaddr; -struct in_addr; -typedef struct socket * ksocket_t; - -/* BSD socket APIs prototype declaration */ -extern ksocket_t ksocket(int domain, int type, int protocol); -extern int kshutdown(ksocket_t socket, int how); -extern int kclose(ksocket_t socket); - -extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); -extern int klisten(ksocket_t socket, int backlog); -extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); -extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); - -extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); -extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); -extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); -extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); - -extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); -extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); -extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); -extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); - -extern unsigned int inet_addr(char* ip); -extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ - -#endif /* !_ksocket_h_ */ diff --git a/sample/udp/udp_client.c b/sample/udp/udp_client.c deleted file mode 100644 index 3e3cd4b..0000000 --- a/sample/udp/udp_client.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define SERVER_PORT 4444 -#define SERVER_IP "127.0.0.1" -#define TIMEOUT_SEC 2 - -int main() { - int sockfd; - struct sockaddr_in server_addr; - char buffer[256]; - const char *message = "Hello UDP Server"; - - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) { - perror("socket"); - exit(EXIT_FAILURE); - } - - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(SERVER_PORT); - - if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) { - perror("inet_pton"); - close(sockfd); - exit(EXIT_FAILURE); - } - - if (sendto(sockfd, message, strlen(message), 0, - (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - perror("sendto"); - close(sockfd); - exit(EXIT_FAILURE); - } - - printf("[client] Sent: %s\n", message); - - // Set receive timeout - struct timeval tv; - tv.tv_sec = TIMEOUT_SEC; - tv.tv_usec = 0; - if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - close(sockfd); - exit(EXIT_FAILURE); - } - - socklen_t addr_len = sizeof(server_addr); - int len = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, - (struct sockaddr *)&server_addr, &addr_len); - if (len < 0) { - perror("[client] No response from server (timeout or unreachable)"); - } else { - buffer[len] = '\0'; - printf("[client] Received: %s\n", buffer); - } - - close(sockfd); - return 0; -} diff --git a/sample/udp/udp_server.c b/sample/udp/udp_server.c deleted file mode 100644 index 50e93ec..0000000 --- a/sample/udp/udp_server.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ksocket.h" - -int udp_server_fn(void *data); -static struct task_struct *server_thread; - -int udp_server_fn(void *data) { - struct socket *sock; - struct sockaddr_in addr; - int ret; - char buffer[256]; - - sock = ksocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (!sock) { - printk(KERN_ERR "UDP Server: Failed to create socket\n"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(4444); - - ret = kbind(sock, (struct sockaddr *)&addr, sizeof(addr)); - if (ret < 0) { - printk(KERN_ERR "UDP Server: Bind failed (%d)\n", ret); - kclose(sock); - return ret; - } - - printk(KERN_INFO "UDP Server: Listening on port 4444\n"); - - while (!kthread_should_stop()) { - struct sockaddr_in src_addr; - int len = sizeof(src_addr); - - memset(buffer, 0, sizeof(buffer)); - ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, 0, - (struct sockaddr *)&src_addr, &len); - if (ret > 0) { - buffer[ret] = '\0'; - printk(KERN_INFO "UDP Server: Received '%s'\n", buffer); - - // Send back acknowledgement - const char *reply = "ACK from UDP Server"; - ksendto(sock, (void *)reply, strlen(reply), 0, - (struct sockaddr *)&src_addr, sizeof(src_addr)); - } - msleep(100); - } - - kclose(sock); - return 0; -} - -static int __init udp_server_init(void) { - server_thread = kthread_run(udp_server_fn, NULL, "udp_server"); - if (IS_ERR(server_thread)) { - printk(KERN_ERR "UDP Server: Failed to create thread\n"); - return PTR_ERR(server_thread); - } - return 0; -} - -static void __exit udp_server_exit(void) { - if (server_thread) - kthread_stop(server_thread); - printk(KERN_INFO "UDP Server: Exited\n"); -} - -module_init(udp_server_init); -module_exit(udp_server_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Simple UDP Server Example with ACK"); -MODULE_AUTHOR("Mephistolist"); From 4ed2a90bf5bd206195beff62cb4a668c26f6baff Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:48:40 +0000 Subject: [PATCH 36/63] Update tcp_server.c --- samples/tcp/server/tcp_server.c | 190 ++++++++++++++++++-------------- 1 file changed, 110 insertions(+), 80 deletions(-) diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c index e315657..e37ce1b 100644 --- a/samples/tcp/server/tcp_server.c +++ b/samples/tcp/server/tcp_server.c @@ -4,113 +4,141 @@ #include #include #include -#include +#include #include #include -#include "ksocket.h" +#include +#include +#include + +#define SERVER_PORT 12345 +#define BACKLOG 5 +#define RECV_BUF_SZ 1024 static struct task_struct *server_thread; -static ksocket_t sockfd = NULL; /* global so exit can access it */ - -/* TCP server thread function */ -static int tcp_server_fn(void *data) { - ksocket_t client_sock; - struct sockaddr_in server_addr, client_addr; - int addr_len = sizeof(struct sockaddr_in); - char buf[128]; - int len; - - sockfd = ksocket(AF_INET, SOCK_STREAM, 0); - if (IS_ERR(sockfd)) { - long err = PTR_ERR(sockfd); - printk(KERN_ERR "ksocket: ksocket() failed: %ld\n", err); - sockfd = NULL; - return (int)err; - } +static struct socket *listen_sock; + +static int tcp_server_thread(void *data) { + struct socket *newsock = NULL; + struct sockaddr_in addr; + int ret; - /* allow immediate reuse of the port */ - { - int optval = 1; - ksetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(optval)); + pr_info("tcp_server: thread starting\n"); + + /* Create kernel socket properly for kernel context */ + ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, IPPROTO_TCP, &listen_sock); + if (ret) { + pr_err("tcp_server: sock_create_kern failed: %d\n", ret); + listen_sock = NULL; + return ret; } + pr_debug("tcp_server: created listen_sock=%p\n", listen_sock); - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htonl(INADDR_ANY); - server_addr.sin_port = htons(12345); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(SERVER_PORT); - if (kbind(sockfd, (struct sockaddr *)&server_addr, addr_len) < 0) { - printk(KERN_ERR "ksocket: bind failed\n"); - kclose(sockfd); - sockfd = NULL; - return -EINVAL; + ret = kernel_bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + if (ret) { + pr_err("tcp_server: kernel_bind failed: %d\n", ret); + goto out_release_listen; } - if (klisten(sockfd, 5) < 0) { - printk(KERN_ERR "ksocket: listen failed\n"); - kclose(sockfd); - sockfd = NULL; - return -EINVAL; + ret = kernel_listen(listen_sock, BACKLOG); + if (ret) { + pr_err("tcp_server: kernel_listen failed: %d\n", ret); + goto out_release_listen; } - printk(KERN_INFO "ksocket: TCP server listening on port 12345...\n"); + pr_info("tcp_server: listening on port %d\n", SERVER_PORT); + /* main accept loop (will exit when thread asked to stop) */ while (!kthread_should_stop()) { - if (!sockfd) - break; - - client_sock = kaccept(sockfd, (struct sockaddr *)&client_addr, &addr_len); - if (IS_ERR(client_sock)) { - long err = PTR_ERR(client_sock); - /* if interrupted or shutdown, will get -ERESTARTSYS/-EINTR/-ECONNABORTED etc */ - if (kthread_should_stop()) { - break; - } - printk(KERN_DEBUG "ksocket: kaccept() returned err %ld\n", err); - msleep(100); - continue; - } - - memset(buf, 0, sizeof(buf)); - len = krecv(client_sock, buf, sizeof(buf) - 1, 0); - if (len > 0) { - buf[len] = '\0'; - printk(KERN_INFO "ksocket: Received: %s\n", buf); + /* kernel_accept may block; that's fine in this thread context */ + ret = kernel_accept(listen_sock, &newsock, 0); + if (ret < 0) { + /* If interrupted or shutting down, break cleanly */ + if (ret == -EINTR || ret == -ERESTARTSYS || kthread_should_stop()) { + pr_info("tcp_server: accept interrupted or thread stopping: %d\n", ret); + break; + } + pr_warn("tcp_server: kernel_accept returned: %d - sleeping then retry\n", ret); + msleep(100); + continue; + } + + if (!newsock) { + pr_warn("tcp_server: kernel_accept returned NULL newsock\n"); + msleep(100); + continue; } - kclose(client_sock); + pr_info("tcp_server: accepted newsock=%p newsock->sk=%p\n", newsock, newsock->sk); + + /* Receive a single message (blocking) and then close */ + { + char *buf = kmalloc(RECV_BUF_SZ, GFP_KERNEL); + if (!buf) { + pr_err("tcp_server: kmalloc failed\n"); + sock_release(newsock); + newsock = NULL; + continue; + } + + { + struct kvec iov = { .iov_base = buf, .iov_len = RECV_BUF_SZ - 1 }; + struct msghdr msg; + int n; + + memset(&msg, 0, sizeof(msg)); + n = kernel_recvmsg(newsock, &msg, &iov, 1, RECV_BUF_SZ - 1, 0); + if (n > 0) { + buf[n] = '\0'; + pr_info("tcp_server: received (%d bytes): %s\n", n, buf); + } else { + pr_info("tcp_server: kernel_recvmsg returned %d\n", n); + } + } + + kfree(buf); + } + + /* close connection */ + sock_release(newsock); + newsock = NULL; } - /* clean up listen socket if still present */ - if (sockfd) { - kclose(sockfd); - sockfd = NULL; +out_release_listen: + if (listen_sock) { + /* release listening socket */ + pr_info("tcp_server: closing listen socket %p\n", listen_sock); + sock_release(listen_sock); + listen_sock = NULL; } + pr_info("tcp_server: thread exiting\n"); return 0; } -/* module init: start the server thread */ static int __init tcp_server_init(void) { - printk(KERN_INFO "ksocket: Loading TCP server module...\n"); - - server_thread = kthread_run(tcp_server_fn, NULL, "tcp_server_thread"); + pr_info("tcp_server: Loading (starting thread)\n"); + server_thread = kthread_run(tcp_server_thread, NULL, "tcp_server_thread"); if (IS_ERR(server_thread)) { - printk(KERN_ERR "ksocket: Failed to start server thread\n"); + int err = PTR_ERR(server_thread); + pr_err("tcp_server: kthread_run failed: %d\n", err); server_thread = NULL; - return PTR_ERR(server_thread); + return err; } - return 0; } -/* module exit: shutdown socket (to unblock accept) and stop thread */ static void __exit tcp_server_exit(void) { - printk(KERN_INFO "ksocket: Unloading TCP server module...\n"); + pr_info("tcp_server: Unloading\n"); - /* Ask the socket to shutdown so blocking accept/recv is interrupted */ - if (sockfd) { - kshutdown(sockfd, 2); /* SHUT_RDWR */ + /* Shutdown listening socket to interrupt accept */ + if (listen_sock) { + kernel_sock_shutdown(listen_sock, SHUT_RDWR); } /* Stop the thread (waits for it to exit) */ @@ -119,16 +147,18 @@ static void __exit tcp_server_exit(void) { server_thread = NULL; } - /* If socket wasn't closed by thread, close it here */ - if (sockfd) { - kclose(sockfd); - sockfd = NULL; + /* If still present, release listen socket (thread may have done it) */ + if (listen_sock) { + sock_release(listen_sock); + listen_sock = NULL; } + + pr_info("tcp_server: Unloaded\n"); } module_init(tcp_server_init); module_exit(tcp_server_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Simple TCP Server Example"); MODULE_AUTHOR("Mephistolist"); +MODULE_DESCRIPTION("Kernel-space TCP server"); From 2567f730b0cb8eb4a4bd1cb5069d1aa09f00c2bc Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:49:37 +0000 Subject: [PATCH 37/63] Update tcp_server.c --- samples/tcp/server/tcp_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c index e37ce1b..0b26b1d 100644 --- a/samples/tcp/server/tcp_server.c +++ b/samples/tcp/server/tcp_server.c @@ -161,4 +161,4 @@ module_exit(tcp_server_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mephistolist"); -MODULE_DESCRIPTION("Kernel-space TCP server"); +MODULE_DESCRIPTION("Kernel-space TCP server using ksocket"); From ce0bad7ad4fa008181a4bd0023ac35fd6fdacce7 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:05:48 +0000 Subject: [PATCH 38/63] Update ksocket.h --- samples/tcp/client/ksocket.h | 393 +++-------------------------------- 1 file changed, 32 insertions(+), 361 deletions(-) diff --git a/samples/tcp/client/ksocket.h b/samples/tcp/client/ksocket.h index 2b1ed6d..807a582 100644 --- a/samples/tcp/client/ksocket.h +++ b/samples/tcp/client/ksocket.h @@ -16,364 +16,35 @@ * Mephistolist (cloneozone@gmail.com) * Changes for kernels 5.11 through at least 6.16. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ksocket.h" - -#define KSOCKET_NAME "ksocket" -#define KSOCKET_VERSION "0.0.3" -#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" -#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ - "blog: https://myresume.sh" -#define KSOCKET_DATE "2025-08-03" - -MODULE_AUTHOR(KSOCKET_AUTHOR); -MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); -MODULE_LICENSE("Dual BSD/GPL"); - -ksocket_t ksocket(int domain, int type, int protocol) { - struct socket *sk = NULL; - int ret = 0; - - ret = sock_create(domain, type, protocol, &sk); - if (ret < 0) { - printk(KERN_INFO "sock_create failed\n"); - return NULL; - } - - printk("sock_create sk= 0x%p\n", sk); - - return sk; -} - -int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - ret = sk->ops->bind(sk, address, address_len); - printk("kbind ret = %d\n", ret); - - return ret; -} - -int klisten(ksocket_t socket, int backlog) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - - if ((unsigned)backlog > SOMAXCONN) { - backlog = SOMAXCONN; - } - - ret = sk->ops->listen(sk, backlog); - - return ret; -} - -int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); - - return ret; -} - -ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct socket *new_sk = NULL; - int ret; - - sk = (struct socket *)socket; - - printk("family = %d, type = %d, protocol = %d\n", - sk->sk->sk_family, sk->type, sk->sk->sk_protocol); - //new_sk = sock_alloc(); - //sock_alloc() is not exported, so i use sock_create() instead - ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); - if (ret < 0) { - return NULL; - } - if (!new_sk) { - return NULL; - } - - new_sk->type = sk->type; - new_sk->ops = sk->ops; - - ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); - if (ret < 0) { - goto error_kaccept; - } - - if (address) { - ret = new_sk->ops->getname(new_sk, address, 1); - if (ret < 0) { - goto error_kaccept; - } - } - - - return new_sk; - -error_kaccept: - sock_release(new_sk); - return NULL; -} - -ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = { 0 }; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - iov.iov_base = buffer; - iov.iov_len = length; - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - if (ret < 0) { - goto out_krecv; - } - -out_krecv: - return ret; -} - -ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int len; - - sk = (struct socket *)socket; - - iov.iov_base = (void *)buffer; - iov.iov_len = length; - - len = kernel_sendmsg(sk, &msg, &iov, 1, length); - return len; -} - -int kshutdown(ksocket_t socket, int how) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - if (sk) { - ret = sk->ops->shutdown(sk, how); - } - return ret; -} - -//TODO: ? -int kclose(ksocket_t socket) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->release(sk); - - if (sk) { - sock_release(sk); - } - return ret; -} - -ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, - int flags, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - // Set up kvec for kernel buffer - iov.iov_base = buffer; - iov.iov_len = length; - - // Set the msg_name and msg_namelen if address is requested - if (address && address_len) { - msg.msg_name = address; - msg.msg_namelen = *address_len; - } - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - - // Update actual received address length - if (ret >= 0 && address_len && msg.msg_namelen > 0) { - *address_len = msg.msg_namelen; - } - return ret; -} - -ssize_t ksendto(ksocket_t socket, void *message, size_t length, - int flags, const struct sockaddr *dest_addr, int dest_len) { - struct socket *sk = (struct socket *)socket; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - // Set up kvec for kernel-safe buffer - iov.iov_base = message; - iov.iov_len = length; - - // Populate destination if provided - if (dest_addr) { - msg.msg_name = (void *)dest_addr; - msg.msg_namelen = dest_len; - } - - msg.msg_flags = flags; - - // Use kernel_sendmsg for modern compatibility - ret = kernel_sendmsg(sk, &msg, &iov, 1, length); - return ret; -} - -int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getsockname(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) { - *address_len = sizeof(addr); - } - } - - return 0; -} - -int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getpeername(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) - *address_len = sizeof(addr); - } - - return 0; -} - -int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { - struct socket *sk = (struct socket *)socket; - sockptr_t opt_ptr; - int ret; - - // Wrap kernel pointer as a safe sockptr_t - opt_ptr = KERNEL_SOCKPTR(optval); - - if (level == SOL_SOCKET) { - ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); - } - else { - ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); - } - return ret; -} - -int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { - struct socket *sk = (struct socket *)socket; - int ret; - - if (!sk || !sk->ops || !sk->ops->getsockopt) { - return -ENOSYS; - } - ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); - - return ret; -} - -//helper functions -unsigned int inet_addr(char* ip) { - int a, b, c, d; - char addr[4]; - - sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); - addr[0] = a; - addr[1] = b; - addr[2] = c; - addr[3] = d; - - return *(unsigned int *)addr; -} - -char *inet_ntoa(struct in_addr *in) { - char* str_ip = NULL; - u_int32_t int_ip = 0; - - str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); - if (!str_ip) { - return NULL; - } - else { - memset(str_ip, 0, 16); - } - int_ip = in->s_addr; - - sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, - (int_ip >> 8 ) & 0xFF, - (int_ip >> 16) & 0xFF, - (int_ip >> 24) & 0xFF); - return str_ip; -} - -//module init and cleanup procedure -static int ksocket_init(void) { - printk("%s version %s\n%s\n%s\n", - KSOCKET_NAME, KSOCKET_VERSION, - KSOCKET_DESCPT, KSOCKET_AUTHOR); - - return 0; -} - -static void ksocket_exit(void) { - printk("ksocket exit\n"); -} - -module_init(ksocket_init); -module_exit(ksocket_exit); - -EXPORT_SYMBOL(ksocket); -EXPORT_SYMBOL(kbind); -EXPORT_SYMBOL(klisten); -EXPORT_SYMBOL(kconnect); -EXPORT_SYMBOL(kaccept); -EXPORT_SYMBOL(krecv); -EXPORT_SYMBOL(ksend); -EXPORT_SYMBOL(kshutdown); -EXPORT_SYMBOL(kclose); -EXPORT_SYMBOL(krecvfrom); -EXPORT_SYMBOL(ksendto); -EXPORT_SYMBOL(kgetsockname); -EXPORT_SYMBOL(kgetpeername); -EXPORT_SYMBOL(ksetsockopt); -EXPORT_SYMBOL(kgetsockopt); -EXPORT_SYMBOL(inet_addr); -EXPORT_SYMBOL(inet_ntoa); +#ifndef _ksocket_h_ +#define _ksocket_h_ + +struct socket; +struct sockaddr; +struct in_addr; +typedef struct socket * ksocket_t; + +/* BSD socket APIs prototype declaration */ +extern ksocket_t ksocket(int domain, int type, int protocol); +extern int kshutdown(ksocket_t socket, int how); +extern int kclose(ksocket_t socket); + +extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); +extern int klisten(ksocket_t socket, int backlog); +extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); +extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); + +extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); +extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); +extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); +extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); + +extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); +extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); + +extern unsigned int inet_addr(char* ip); +extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ + +#endif /* !_ksocket_h_ */ From 750f2949e6a61b8aeda54949b93ac359a874aca9 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 04:59:21 +0000 Subject: [PATCH 39/63] Update ksocket.h --- samples/udp/server/ksocket.h | 397 +++-------------------------------- 1 file changed, 34 insertions(+), 363 deletions(-) diff --git a/samples/udp/server/ksocket.h b/samples/udp/server/ksocket.h index 2b1ed6d..d32fa99 100644 --- a/samples/udp/server/ksocket.h +++ b/samples/udp/server/ksocket.h @@ -7,373 +7,44 @@ * * This code is licenced under the GPL * Feel free to contact me if any questions - * + * * @2017 * Hardik Bagdi (hbagdi1@binghamton.edu) * Changes for Compatibility with Linux 4.9 to use iov_iter - * + * * @2025 * Mephistolist (cloneozone@gmail.com) * Changes for kernels 5.11 through at least 6.16. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ksocket.h" - -#define KSOCKET_NAME "ksocket" -#define KSOCKET_VERSION "0.0.3" -#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" -#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ - "blog: https://myresume.sh" -#define KSOCKET_DATE "2025-08-03" - -MODULE_AUTHOR(KSOCKET_AUTHOR); -MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); -MODULE_LICENSE("Dual BSD/GPL"); - -ksocket_t ksocket(int domain, int type, int protocol) { - struct socket *sk = NULL; - int ret = 0; - - ret = sock_create(domain, type, protocol, &sk); - if (ret < 0) { - printk(KERN_INFO "sock_create failed\n"); - return NULL; - } - - printk("sock_create sk= 0x%p\n", sk); - - return sk; -} - -int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - ret = sk->ops->bind(sk, address, address_len); - printk("kbind ret = %d\n", ret); - - return ret; -} - -int klisten(ksocket_t socket, int backlog) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - - if ((unsigned)backlog > SOMAXCONN) { - backlog = SOMAXCONN; - } - - ret = sk->ops->listen(sk, backlog); - - return ret; -} - -int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); - - return ret; -} - -ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct socket *new_sk = NULL; - int ret; - - sk = (struct socket *)socket; - - printk("family = %d, type = %d, protocol = %d\n", - sk->sk->sk_family, sk->type, sk->sk->sk_protocol); - //new_sk = sock_alloc(); - //sock_alloc() is not exported, so i use sock_create() instead - ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); - if (ret < 0) { - return NULL; - } - if (!new_sk) { - return NULL; - } - - new_sk->type = sk->type; - new_sk->ops = sk->ops; - - ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); - if (ret < 0) { - goto error_kaccept; - } - - if (address) { - ret = new_sk->ops->getname(new_sk, address, 1); - if (ret < 0) { - goto error_kaccept; - } - } - - - return new_sk; - -error_kaccept: - sock_release(new_sk); - return NULL; -} - -ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = { 0 }; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - iov.iov_base = buffer; - iov.iov_len = length; - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - if (ret < 0) { - goto out_krecv; - } - -out_krecv: - return ret; -} - -ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int len; - - sk = (struct socket *)socket; - - iov.iov_base = (void *)buffer; - iov.iov_len = length; - - len = kernel_sendmsg(sk, &msg, &iov, 1, length); - return len; -} - -int kshutdown(ksocket_t socket, int how) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - if (sk) { - ret = sk->ops->shutdown(sk, how); - } - return ret; -} - -//TODO: ? -int kclose(ksocket_t socket) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->release(sk); - - if (sk) { - sock_release(sk); - } - return ret; -} - -ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, - int flags, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - // Set up kvec for kernel buffer - iov.iov_base = buffer; - iov.iov_len = length; - - // Set the msg_name and msg_namelen if address is requested - if (address && address_len) { - msg.msg_name = address; - msg.msg_namelen = *address_len; - } - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - - // Update actual received address length - if (ret >= 0 && address_len && msg.msg_namelen > 0) { - *address_len = msg.msg_namelen; - } - return ret; -} - -ssize_t ksendto(ksocket_t socket, void *message, size_t length, - int flags, const struct sockaddr *dest_addr, int dest_len) { - struct socket *sk = (struct socket *)socket; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - // Set up kvec for kernel-safe buffer - iov.iov_base = message; - iov.iov_len = length; - - // Populate destination if provided - if (dest_addr) { - msg.msg_name = (void *)dest_addr; - msg.msg_namelen = dest_len; - } - - msg.msg_flags = flags; - - // Use kernel_sendmsg for modern compatibility - ret = kernel_sendmsg(sk, &msg, &iov, 1, length); - return ret; -} - -int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getsockname(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) { - *address_len = sizeof(addr); - } - } - - return 0; -} - -int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getpeername(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) - *address_len = sizeof(addr); - } - - return 0; -} - -int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { - struct socket *sk = (struct socket *)socket; - sockptr_t opt_ptr; - int ret; - - // Wrap kernel pointer as a safe sockptr_t - opt_ptr = KERNEL_SOCKPTR(optval); - - if (level == SOL_SOCKET) { - ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); - } - else { - ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); - } - return ret; -} - -int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { - struct socket *sk = (struct socket *)socket; - int ret; - - if (!sk || !sk->ops || !sk->ops->getsockopt) { - return -ENOSYS; - } - ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); - - return ret; -} - -//helper functions -unsigned int inet_addr(char* ip) { - int a, b, c, d; - char addr[4]; - - sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); - addr[0] = a; - addr[1] = b; - addr[2] = c; - addr[3] = d; - - return *(unsigned int *)addr; -} - -char *inet_ntoa(struct in_addr *in) { - char* str_ip = NULL; - u_int32_t int_ip = 0; - - str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); - if (!str_ip) { - return NULL; - } - else { - memset(str_ip, 0, 16); - } - int_ip = in->s_addr; - - sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, - (int_ip >> 8 ) & 0xFF, - (int_ip >> 16) & 0xFF, - (int_ip >> 24) & 0xFF); - return str_ip; -} - -//module init and cleanup procedure -static int ksocket_init(void) { - printk("%s version %s\n%s\n%s\n", - KSOCKET_NAME, KSOCKET_VERSION, - KSOCKET_DESCPT, KSOCKET_AUTHOR); - - return 0; -} - -static void ksocket_exit(void) { - printk("ksocket exit\n"); -} - -module_init(ksocket_init); -module_exit(ksocket_exit); - -EXPORT_SYMBOL(ksocket); -EXPORT_SYMBOL(kbind); -EXPORT_SYMBOL(klisten); -EXPORT_SYMBOL(kconnect); -EXPORT_SYMBOL(kaccept); -EXPORT_SYMBOL(krecv); -EXPORT_SYMBOL(ksend); -EXPORT_SYMBOL(kshutdown); -EXPORT_SYMBOL(kclose); -EXPORT_SYMBOL(krecvfrom); -EXPORT_SYMBOL(ksendto); -EXPORT_SYMBOL(kgetsockname); -EXPORT_SYMBOL(kgetpeername); -EXPORT_SYMBOL(ksetsockopt); -EXPORT_SYMBOL(kgetsockopt); -EXPORT_SYMBOL(inet_addr); -EXPORT_SYMBOL(inet_ntoa); +#ifndef _ksocket_h_ +#define _ksocket_h_ + +struct socket; +struct sockaddr; +struct in_addr; +typedef struct socket * ksocket_t; + +/* BSD socket APIs prototype declaration */ +extern ksocket_t ksocket(int domain, int type, int protocol); +extern int kshutdown(ksocket_t socket, int how); +extern int kclose(ksocket_t socket); + +extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); +extern int klisten(ksocket_t socket, int backlog); +extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); +extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); + +extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); +extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); +extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); +extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); + +extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); +extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); + +extern unsigned int inet_addr(char* ip); +extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ + +#endif /* !_ksocket_h_ */ From 08720147a07fc0a1063d85d9b9bf0265d9836355 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:00:45 +0000 Subject: [PATCH 40/63] Update ksocket.h --- samples/udp/client/ksocket.h | 397 +++-------------------------------- 1 file changed, 34 insertions(+), 363 deletions(-) diff --git a/samples/udp/client/ksocket.h b/samples/udp/client/ksocket.h index 2b1ed6d..d32fa99 100644 --- a/samples/udp/client/ksocket.h +++ b/samples/udp/client/ksocket.h @@ -7,373 +7,44 @@ * * This code is licenced under the GPL * Feel free to contact me if any questions - * + * * @2017 * Hardik Bagdi (hbagdi1@binghamton.edu) * Changes for Compatibility with Linux 4.9 to use iov_iter - * + * * @2025 * Mephistolist (cloneozone@gmail.com) * Changes for kernels 5.11 through at least 6.16. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ksocket.h" - -#define KSOCKET_NAME "ksocket" -#define KSOCKET_VERSION "0.0.3" -#define KSOCKET_DESCPT "BSD-style socket APIs for kernels 5.11 - 6.16.x" -#define KSOCKET_AUTHOR "mail : cloneozone@gmail.com\n"\ - "blog: https://myresume.sh" -#define KSOCKET_DATE "2025-08-03" - -MODULE_AUTHOR(KSOCKET_AUTHOR); -MODULE_DESCRIPTION(KSOCKET_NAME"-"KSOCKET_VERSION"\n"KSOCKET_DESCPT); -MODULE_LICENSE("Dual BSD/GPL"); - -ksocket_t ksocket(int domain, int type, int protocol) { - struct socket *sk = NULL; - int ret = 0; - - ret = sock_create(domain, type, protocol, &sk); - if (ret < 0) { - printk(KERN_INFO "sock_create failed\n"); - return NULL; - } - - printk("sock_create sk= 0x%p\n", sk); - - return sk; -} - -int kbind(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - ret = sk->ops->bind(sk, address, address_len); - printk("kbind ret = %d\n", ret); - - return ret; -} - -int klisten(ksocket_t socket, int backlog) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - - if ((unsigned)backlog > SOMAXCONN) { - backlog = SOMAXCONN; - } - - ret = sk->ops->listen(sk, backlog); - - return ret; -} - -int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); - - return ret; -} - -ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct socket *new_sk = NULL; - int ret; - - sk = (struct socket *)socket; - - printk("family = %d, type = %d, protocol = %d\n", - sk->sk->sk_family, sk->type, sk->sk->sk_protocol); - //new_sk = sock_alloc(); - //sock_alloc() is not exported, so i use sock_create() instead - ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); - if (ret < 0) { - return NULL; - } - if (!new_sk) { - return NULL; - } - - new_sk->type = sk->type; - new_sk->ops = sk->ops; - - ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); - if (ret < 0) { - goto error_kaccept; - } - - if (address) { - ret = new_sk->ops->getname(new_sk, address, 1); - if (ret < 0) { - goto error_kaccept; - } - } - - - return new_sk; - -error_kaccept: - sock_release(new_sk); - return NULL; -} - -ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = { 0 }; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - iov.iov_base = buffer; - iov.iov_len = length; - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - if (ret < 0) { - goto out_krecv; - } - -out_krecv: - return ret; -} - -ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int len; - - sk = (struct socket *)socket; - - iov.iov_base = (void *)buffer; - iov.iov_len = length; - - len = kernel_sendmsg(sk, &msg, &iov, 1, length); - return len; -} - -int kshutdown(ksocket_t socket, int how) { - struct socket *sk; - int ret = 0; - - sk = (struct socket *)socket; - if (sk) { - ret = sk->ops->shutdown(sk, how); - } - return ret; -} - -//TODO: ? -int kclose(ksocket_t socket) { - struct socket *sk; - int ret; - - sk = (struct socket *)socket; - ret = sk->ops->release(sk); - - if (sk) { - sock_release(sk); - } - return ret; -} - -ssize_t krecvfrom(ksocket_t socket, void *buffer, size_t length, - int flags, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - // Set up kvec for kernel buffer - iov.iov_base = buffer; - iov.iov_len = length; - - // Set the msg_name and msg_namelen if address is requested - if (address && address_len) { - msg.msg_name = address; - msg.msg_namelen = *address_len; - } - - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - - // Update actual received address length - if (ret >= 0 && address_len && msg.msg_namelen > 0) { - *address_len = msg.msg_namelen; - } - return ret; -} - -ssize_t ksendto(ksocket_t socket, void *message, size_t length, - int flags, const struct sockaddr *dest_addr, int dest_len) { - struct socket *sk = (struct socket *)socket; - struct msghdr msg = {0}; - struct kvec iov; - int ret; - - // Set up kvec for kernel-safe buffer - iov.iov_base = message; - iov.iov_len = length; - - // Populate destination if provided - if (dest_addr) { - msg.msg_name = (void *)dest_addr; - msg.msg_namelen = dest_len; - } - - msg.msg_flags = flags; - - // Use kernel_sendmsg for modern compatibility - ret = kernel_sendmsg(sk, &msg, &iov, 1, length); - return ret; -} - -int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getsockname(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) { - *address_len = sizeof(addr); - } - } - - return 0; -} - -int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk = (struct socket *)socket; - struct sockaddr_storage addr; - int ret; - - ret = kernel_getpeername(sk, (struct sockaddr *)&addr); - if (ret < 0) { - return ret; - } - if (address) { - memcpy(address, &addr, sizeof(addr)); - if (address_len) - *address_len = sizeof(addr); - } - - return 0; -} - -int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) { - struct socket *sk = (struct socket *)socket; - sockptr_t opt_ptr; - int ret; - - // Wrap kernel pointer as a safe sockptr_t - opt_ptr = KERNEL_SOCKPTR(optval); - - if (level == SOL_SOCKET) { - ret = sock_setsockopt(sk, level, optname, opt_ptr, optlen); - } - else { - ret = sk->ops->setsockopt(sk, level, optname, opt_ptr, optlen); - } - return ret; -} - -int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) { - struct socket *sk = (struct socket *)socket; - int ret; - - if (!sk || !sk->ops || !sk->ops->getsockopt) { - return -ENOSYS; - } - ret = sk->ops->getsockopt(sk, level, optname, (char *)optval, optlen); - - return ret; -} - -//helper functions -unsigned int inet_addr(char* ip) { - int a, b, c, d; - char addr[4]; - - sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); - addr[0] = a; - addr[1] = b; - addr[2] = c; - addr[3] = d; - - return *(unsigned int *)addr; -} - -char *inet_ntoa(struct in_addr *in) { - char* str_ip = NULL; - u_int32_t int_ip = 0; - - str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); - if (!str_ip) { - return NULL; - } - else { - memset(str_ip, 0, 16); - } - int_ip = in->s_addr; - - sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, - (int_ip >> 8 ) & 0xFF, - (int_ip >> 16) & 0xFF, - (int_ip >> 24) & 0xFF); - return str_ip; -} - -//module init and cleanup procedure -static int ksocket_init(void) { - printk("%s version %s\n%s\n%s\n", - KSOCKET_NAME, KSOCKET_VERSION, - KSOCKET_DESCPT, KSOCKET_AUTHOR); - - return 0; -} - -static void ksocket_exit(void) { - printk("ksocket exit\n"); -} - -module_init(ksocket_init); -module_exit(ksocket_exit); - -EXPORT_SYMBOL(ksocket); -EXPORT_SYMBOL(kbind); -EXPORT_SYMBOL(klisten); -EXPORT_SYMBOL(kconnect); -EXPORT_SYMBOL(kaccept); -EXPORT_SYMBOL(krecv); -EXPORT_SYMBOL(ksend); -EXPORT_SYMBOL(kshutdown); -EXPORT_SYMBOL(kclose); -EXPORT_SYMBOL(krecvfrom); -EXPORT_SYMBOL(ksendto); -EXPORT_SYMBOL(kgetsockname); -EXPORT_SYMBOL(kgetpeername); -EXPORT_SYMBOL(ksetsockopt); -EXPORT_SYMBOL(kgetsockopt); -EXPORT_SYMBOL(inet_addr); -EXPORT_SYMBOL(inet_ntoa); +#ifndef _ksocket_h_ +#define _ksocket_h_ + +struct socket; +struct sockaddr; +struct in_addr; +typedef struct socket * ksocket_t; + +/* BSD socket APIs prototype declaration */ +extern ksocket_t ksocket(int domain, int type, int protocol); +extern int kshutdown(ksocket_t socket, int how); +extern int kclose(ksocket_t socket); + +extern int kbind(ksocket_t socket, struct sockaddr *address, int address_len); +extern int klisten(ksocket_t socket, int backlog); +extern int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); +extern ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); + +extern ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); +extern ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); +extern ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); +extern ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); + +extern int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); +extern int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); +extern int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); + +extern unsigned int inet_addr(char* ip); +extern char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ + +#endif /* !_ksocket_h_ */ From ce58935f243257fd902d3884711dc1d73350a7e2 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:09:49 +0000 Subject: [PATCH 41/63] Update README.md --- README.md | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 986294b..2435ef9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # ksocket API -BSD-style socket API in kernel space for TCP/IP networking. +BSD-style socket API in kernel space for TCP/IP networking on Linux kernels 5.11-6.16. + Original ksocket for v2.6 was published at [http://ksocket.sourceforge.net/](http://ksocket.sourceforge.net/). This repository contains changes to make it compatible with new kernel versions. The ksocket API has been updated to incorporate the changes related to the [iov_iter](https://lwn.net/Articles/625077/) interface introduced in kernel v3.19+. @@ -13,10 +14,33 @@ $ make # make sure you have the kernel headers/tree installed first $ sudo insmod ksocket.ko #now you can use the exported symbols from this kernel module ``` - +You can then go to the samples directory in the root of this project. Inside it are TCP and UDP of servers and client examples you may build and insert into the kernel. After inserting the server and client for TCP, you should see something like the following with dmesg: +``` +# dmesg +[ 137.259240] tcp_server: Loading (starting thread) +[ 137.260232] tcp_server: thread starting +[ 137.260634] tcp_server: listening on port 12345 +[ 151.256262] [tcp_client] Initializing +[ 151.257245] sock_create sk= 0x00000000db4a0058 +[ 151.264826] [tcp_client] Connected to 127.0.0.1:12345 +[ 151.264886] tcp_server: accepted newsock=000000000aae9c53 newsock->sk=00000000844b247d +[ 151.265311] tcp_server: received (29 bytes): Hello from kernel TCP client! +[ 151.265396] [tcp_client] Sent: Hello from kernel TCP client! +``` +Or with the UDP modules, the dmesg should resemble this: +``` +# dmesg +[ 501.520772] sock_create sk= 0x00000000295150e8 +[ 501.522605] kbind ret = 0 +[ 501.523914] UDP Server: Listening on port 4444 +[ 590.998621] [udp_client] Initializing +[ 591.001210] sock_create sk= 0x000000006da0c70b +[ 591.003466] [udp_client] Sent: Hello UDP Server +[ 591.003636] UDP Server: Received 'Hello UDP Server' +[ 591.062269] [udp_client] Received: ACK from UDP Server +``` ### Support across kernel versions -The original ksocket work was to support Linux 2.6, however support for v5.4.0 was later -included. This version of ksocket was designed for kernels 5.11-6.16. It may work in verions beyond 6.16, but we do not know what future kernel versions will entail. If you need this for an older kernel, see the links below: +The original ksocket work was to support Linux 2.6, and later versions came for later kernels. This version of ksocket was designed for kernels 5.11-6.16. It may work in verions beyond 6.16, but we do not know what future kernel versions will entail. If you need this for an older kernel, see the links below: #### v2.6 original development https://github.com/hbagdi/ksocket @@ -29,4 +53,4 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 - Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. ### Contact -Email at hardikbagdi@gmail.com for any further help. +For this version you may reach out to cloneozone@gmail.com. From e643f64f23021c59fa3c00bc0f5b0d08b3a168eb Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:10:54 +0000 Subject: [PATCH 42/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2435ef9..bae89eb 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 - Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. ### Contact -For this version you may reach out to cloneozone@gmail.com. +For this version of kscoket you may reach out to cloneozone@gmail.com. From e811af4d73fc4c688c4928e0eb889c01044103cb Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:12:24 +0000 Subject: [PATCH 43/63] Update AUTHOR --- AUTHOR | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHOR b/AUTHOR index c0ab6fb..e967559 100644 --- a/AUTHOR +++ b/AUTHOR @@ -6,3 +6,6 @@ song.xian-guang@hotmail.com 2017 Hardik Bagdi(hbagdi1@binghamton.edu) Changes for Compatibility with Linux 4.9 to use iov_iter + +2025 Mephistolist(cloneozone@gmail.com) +Complete rewrite for kernels 5.11-6.16. From a5be4c1b3a29490e23d9f1314fd5197d467423a2 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:17:21 +0000 Subject: [PATCH 44/63] Update README.md --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index bae89eb..b5a241b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # ksocket API -BSD-style socket API in kernel space for TCP/IP networking on Linux kernels 5.11-6.16. - -Original ksocket for v2.6 was published at [http://ksocket.sourceforge.net/](http://ksocket.sourceforge.net/). -This repository contains changes to make it compatible with new kernel versions. -The ksocket API has been updated to incorporate the changes related to the [iov_iter](https://lwn.net/Articles/625077/) interface introduced in kernel v3.19+. +A BSD-style socket API in kernel space for TCP/IP networking on Linux kernels 5.11-6.16. This is not backwards compatible with older kernels, but links will be provided to those later in this documentation. ### Getting started ``` From 274b6ef856ba4c02fcdd5fac9550d24953dc5153 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:49:47 +0000 Subject: [PATCH 45/63] Update ksocket.c --- src/ksocket.c | 90 +++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/src/ksocket.c b/src/ksocket.c index 2b1ed6d..a03175f 100644 --- a/src/ksocket.c +++ b/src/ksocket.c @@ -91,65 +91,49 @@ int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) { } ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) { - struct socket *sk; - struct socket *new_sk = NULL; - int ret; - - sk = (struct socket *)socket; - - printk("family = %d, type = %d, protocol = %d\n", - sk->sk->sk_family, sk->type, sk->sk->sk_protocol); - //new_sk = sock_alloc(); - //sock_alloc() is not exported, so i use sock_create() instead - ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); - if (ret < 0) { - return NULL; - } - if (!new_sk) { - return NULL; - } - - new_sk->type = sk->type; - new_sk->ops = sk->ops; - - ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); - if (ret < 0) { - goto error_kaccept; - } - - if (address) { - ret = new_sk->ops->getname(new_sk, address, 1); - if (ret < 0) { - goto error_kaccept; - } - } - - - return new_sk; + struct socket *sk = (struct socket *)socket; + struct socket *new_sk = NULL; + int ret; + + printk("family = %d, type = %d, protocol = %d\n", + sk->sk->sk_family, sk->type, sk->sk->sk_protocol); + + // Create a new socket + ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); + if (ret < 0 || !new_sk) + return NULL; + + new_sk->type = sk->type; + new_sk->ops = sk->ops; + + // Accept connection + ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); + if (ret < 0) { + sock_release(new_sk); + return NULL; + } + + // Retrieve peer address if requested + if (address) { + ret = new_sk->ops->getname(new_sk, address, 1); + if (ret < 0) { + sock_release(new_sk); + return NULL; + } + } -error_kaccept: - sock_release(new_sk); - return NULL; + return new_sk; } ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) { - struct socket *sk; - struct msghdr msg = { 0 }; - struct kvec iov; - int ret; - - sk = (struct socket *)socket; - - iov.iov_base = buffer; - iov.iov_len = length; + struct socket *sk = (struct socket *)socket; + struct msghdr msg = { 0 }; + struct kvec iov; - ret = kernel_recvmsg(sk, &msg, &iov, 1, length, flags); - if (ret < 0) { - goto out_krecv; - } + iov.iov_base = buffer; + iov.iov_len = length; -out_krecv: - return ret; + return kernel_recvmsg(sk, &msg, &iov, 1, length, flags); } ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) { From b7062963bfd2d6c860788e01dfe521a1a53347a2 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 06:04:06 +0000 Subject: [PATCH 46/63] Update tcp_server.c --- samples/tcp/server/tcp_server.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c index 0b26b1d..3611f9b 100644 --- a/samples/tcp/server/tcp_server.c +++ b/samples/tcp/server/tcp_server.c @@ -42,13 +42,17 @@ static int tcp_server_thread(void *data) { ret = kernel_bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); if (ret) { pr_err("tcp_server: kernel_bind failed: %d\n", ret); - goto out_release_listen; + sock_release(listen_sock); + listen_sock = NULL; + return ret; } ret = kernel_listen(listen_sock, BACKLOG); if (ret) { pr_err("tcp_server: kernel_listen failed: %d\n", ret); - goto out_release_listen; + sock_release(listen_sock); + listen_sock = NULL; + return ret; } pr_info("tcp_server: listening on port %d\n", SERVER_PORT); @@ -109,9 +113,8 @@ static int tcp_server_thread(void *data) { newsock = NULL; } -out_release_listen: + /* cleanup listening socket */ if (listen_sock) { - /* release listening socket */ pr_info("tcp_server: closing listen socket %p\n", listen_sock); sock_release(listen_sock); listen_sock = NULL; From fda2d4882d90f079e64791e599824813eb818816 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Mon, 11 Aug 2025 23:59:02 +0000 Subject: [PATCH 47/63] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b5a241b..61e55eb 100644 --- a/README.md +++ b/README.md @@ -48,5 +48,8 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 - Feel free to open Pull-Requests here for any enhancements/fixes. - Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. +### Stream-lining +If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically ksocket when building a kernel from source. + ### Contact For this version of kscoket you may reach out to cloneozone@gmail.com. From a6fa7504180641a18ab9941aa1d17a1c20f7ff7f Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:14:42 +0000 Subject: [PATCH 48/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61e55eb..52cf29a 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 - Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. ### Stream-lining -If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically ksocket when building a kernel from source. +If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically link ksocket when building a kernel from source. ### Contact For this version of kscoket you may reach out to cloneozone@gmail.com. From 4e4bac3dfe54aff1b09529c7d0b83feab357b13a Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Fri, 15 Aug 2025 23:57:20 +0000 Subject: [PATCH 49/63] Update README.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52cf29a..c4a2dec 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,23 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 ### Contributing/Reporting Bugs - Feel free to open Pull-Requests here for any enhancements/fixes. -- Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. +- Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. ### Stream-lining -If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically link ksocket when building a kernel from source. +If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically link ksocket when building a kernel from source. Considering we have kernel 6.16, and this ksocket project in /home/user/ksocket, we can do something like the following: +``` +# export VERSION=6.16 +# mkdir /usr/src/linux-$VERSION/drivers/ksocket +# rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ +# sed -i '$ s/^endmenu$/source "drivers/ksocket/Kconfig"\nendmenu/' /usr/src/linux-$VERSION/drivers/Kconfig +# echo 'config KSOCKET' > /usr/src/linux-$VERSION/drivers/ksocket/Kconfig +# echo ' bool "Kernel Socket API helper"' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig +# echo ' help' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig +# echo ' Provides a simple kernel-space TCP/UDP socket API wrapper.' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig +# echo ' Needed for your custom kernel networking code.' +``` +If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call this API: +``` KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers ``` ### Contact For this version of kscoket you may reach out to cloneozone@gmail.com. From 0fcffd21ac759cacccc34c60dfe1f7095f51d103 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:10:48 +0000 Subject: [PATCH 50/63] Create Kconfig --- src/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/Kconfig diff --git a/src/Kconfig b/src/Kconfig new file mode 100644 index 0000000..587d661 --- /dev/null +++ b/src/Kconfig @@ -0,0 +1,5 @@ +config KSOCKET + bool "Kernel Socket API helper" + help + Provides a simple kernel-space TCP/UDP socket API wrapper. + Needed for your custom kernel networking code. From fce2fc1fb978039d08d6e772c456127f8d0fe32b Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:11:42 +0000 Subject: [PATCH 51/63] Update README.md --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index c4a2dec..ffc287e 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,6 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # mkdir /usr/src/linux-$VERSION/drivers/ksocket # rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ # sed -i '$ s/^endmenu$/source "drivers/ksocket/Kconfig"\nendmenu/' /usr/src/linux-$VERSION/drivers/Kconfig -# echo 'config KSOCKET' > /usr/src/linux-$VERSION/drivers/ksocket/Kconfig -# echo ' bool "Kernel Socket API helper"' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig -# echo ' help' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig -# echo ' Provides a simple kernel-space TCP/UDP socket API wrapper.' >> /usr/src/linux-$VERSION/drivers/ksocket/Kconfig -# echo ' Needed for your custom kernel networking code.' ``` If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call this API: ``` KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers ``` From 0c1e1f0132ee87d52f1b342fc7d6c218c14fee3e Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:12:18 +0000 Subject: [PATCH 52/63] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ffc287e..393ba11 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # sed -i '$ s/^endmenu$/source "drivers/ksocket/Kconfig"\nendmenu/' /usr/src/linux-$VERSION/drivers/Kconfig ``` If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call this API: -``` KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers ``` +``` +KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers +``` ### Contact For this version of kscoket you may reach out to cloneozone@gmail.com. From 229fb42abb55ea8112aefcc6f96f3ee62a408de4 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:14:34 +0000 Subject: [PATCH 53/63] Update AUTHOR --- AUTHOR | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AUTHOR b/AUTHOR index e967559..345cab6 100644 --- a/AUTHOR +++ b/AUTHOR @@ -1,7 +1,6 @@ -Author +Authors song.xian-guang@hotmail.com - (C)2007-2008, China 2017 Hardik Bagdi(hbagdi1@binghamton.edu) From 6b1f60addc3253db6db2c1c04f80a742fb5b4b2d Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:22:44 +0000 Subject: [PATCH 54/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 393ba11..040c038 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ # sed -i '$ s/^endmenu$/source "drivers/ksocket/Kconfig"\nendmenu/' /usr/src/linux-$VERSION/drivers/Kconfig ``` -If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call this API: +If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call kscoket's API: ``` KBUILD_EXTRA_SYMBOLS := ../../../src/Module.symvers ``` From 1b414bed84dcd6ce5b548f2f6cae9d305b87e96c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sat, 16 Aug 2025 02:47:52 +0000 Subject: [PATCH 55/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 040c038..8fa0123 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ https://github.com/hbagdi/ksocket/tree/linux-5.4.0 - Open an issue in the repository for any help or bugs. Make sure to mention Kernel version. ### Stream-lining -If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically link ksocket when building a kernel from source. Considering we have kernel 6.16, and this ksocket project in /home/user/ksocket, we can do something like the following: +If you wish to not have to load the ksocket module, or link its symbols in Makefiles you can statically link ksocket when building a kernel from source. Considering we have kernel 6.16 inside /usr/src and this ksocket project in /home/user/ksocket, we can do something like the following: ``` # export VERSION=6.16 From f61ac7fed730f1858699ca438d4bd63001cb4185 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Sun, 17 Aug 2025 18:51:39 +0000 Subject: [PATCH 56/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fa0123..4bba0bd 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # export VERSION=6.16 # mkdir /usr/src/linux-$VERSION/drivers/ksocket # rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ -# sed -i '$ s/^endmenu$/source "drivers/ksocket/Kconfig"\nendmenu/' /usr/src/linux-$VERSION/drivers/Kconfig +# sed -i '$ s|^endmenu$|source "drivers/ksocket/Kconfig"\nendmenu|' /usr/src/linux-$VERSION/drivers/Kconfig ``` If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call kscoket's API: ``` From a0b9fff2c8090e54c4bc8879f4ae1c88ab4c50bd Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Tue, 19 Aug 2025 20:44:44 +0000 Subject: [PATCH 57/63] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4bba0bd..413ffff 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # mkdir /usr/src/linux-$VERSION/drivers/ksocket # rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ # sed -i '$ s|^endmenu$|source "drivers/ksocket/Kconfig"\nendmenu|' /usr/src/linux-$VERSION/drivers/Kconfig +echo "obj-$(CONFIG_KSOCKET) += ksocket/" >> /usr/src/linux-$VERSION/drivers/Makefile ``` If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call kscoket's API: ``` From 716dab7acb4075b0c877ceb264f8006363559272 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Tue, 19 Aug 2025 20:45:13 +0000 Subject: [PATCH 58/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 413ffff..cabcef8 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ If you wish to not have to load the ksocket module, or link its symbols in Makef # mkdir /usr/src/linux-$VERSION/drivers/ksocket # rsync -avP /home/user/ksocket/ /usr/src/linux-$VERSION/drivers/ksocket/ # sed -i '$ s|^endmenu$|source "drivers/ksocket/Kconfig"\nendmenu|' /usr/src/linux-$VERSION/drivers/Kconfig -echo "obj-$(CONFIG_KSOCKET) += ksocket/" >> /usr/src/linux-$VERSION/drivers/Makefile +# echo "obj-$(CONFIG_KSOCKET) += ksocket/" >> /usr/src/linux-$VERSION/drivers/Makefile ``` If you proceed with then building and loading your kernel, you will not have to build or insert the ksocket module as it will already be in the kernel. You will also no longer need this line in your Makefiles to use or call kscoket's API: ``` From fbdb304507db8609f3f1916219a8f52689019b0e Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Wed, 20 Aug 2025 04:23:45 +0000 Subject: [PATCH 59/63] Update tcp_server.c --- samples/tcp/server/tcp_server.c | 142 +++++++++++++++----------------- 1 file changed, 68 insertions(+), 74 deletions(-) diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c index 3611f9b..63a3cce 100644 --- a/samples/tcp/server/tcp_server.c +++ b/samples/tcp/server/tcp_server.c @@ -5,118 +5,114 @@ #include #include #include -#include #include -#include -#include -#include +#include /* socket families, SOCK_STREAM */ +#include /* socket options */ +#include "ksocket.h" /* <-- your wrapper API */ #define SERVER_PORT 12345 #define BACKLOG 5 #define RECV_BUF_SZ 1024 static struct task_struct *server_thread; -static struct socket *listen_sock; +static ksocket_t listen_sock = NULL; static int tcp_server_thread(void *data) { - struct socket *newsock = NULL; struct sockaddr_in addr; + int addrlen = sizeof(addr); int ret; - pr_info("tcp_server: thread starting\n"); + pr_info("tcp_server: thread starting (ksocket API)\n"); - /* Create kernel socket properly for kernel context */ - ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, IPPROTO_TCP, &listen_sock); - if (ret) { - pr_err("tcp_server: sock_create_kern failed: %d\n", ret); + /* Create listening socket via ksocket() */ + listen_sock = ksocket(AF_INET, SOCK_STREAM, 0); + if (IS_ERR(listen_sock)) { + long err = PTR_ERR(listen_sock); + pr_err("tcp_server: ksocket() failed: %ld\n", err); listen_sock = NULL; - return ret; + return (int)err; + } + + /* (Optional) allow immediate port reuse */ + { + int optval = 1; + ksetsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, + (void *)&optval, sizeof(optval)); } - pr_debug("tcp_server: created listen_sock=%p\n", listen_sock); memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; + addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(SERVER_PORT); + addr.sin_port = htons(SERVER_PORT); - ret = kernel_bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); - if (ret) { - pr_err("tcp_server: kernel_bind failed: %d\n", ret); - sock_release(listen_sock); + ret = kbind(listen_sock, (struct sockaddr *)&addr, addrlen); + if (ret < 0) { + pr_err("tcp_server: kbind() failed: %d\n", ret); + kclose(listen_sock); listen_sock = NULL; return ret; } - ret = kernel_listen(listen_sock, BACKLOG); - if (ret) { - pr_err("tcp_server: kernel_listen failed: %d\n", ret); - sock_release(listen_sock); + ret = klisten(listen_sock, BACKLOG); + if (ret < 0) { + pr_err("tcp_server: klisten() failed: %d\n", ret); + kclose(listen_sock); listen_sock = NULL; return ret; } pr_info("tcp_server: listening on port %d\n", SERVER_PORT); - /* main accept loop (will exit when thread asked to stop) */ + /* Accept loop */ while (!kthread_should_stop()) { - /* kernel_accept may block; that's fine in this thread context */ - ret = kernel_accept(listen_sock, &newsock, 0); - if (ret < 0) { - /* If interrupted or shutting down, break cleanly */ - if (ret == -EINTR || ret == -ERESTARTSYS || kthread_should_stop()) { - pr_info("tcp_server: accept interrupted or thread stopping: %d\n", ret); + ksocket_t client = NULL; + struct sockaddr_in peer; + int peerlen = sizeof(peer); + int n; + char *buf; + + /* Accept (blocking) */ + client = kaccept(listen_sock, (struct sockaddr *)&peer, &peerlen); + if (IS_ERR_OR_NULL(client)) { + long err = IS_ERR(client) ? PTR_ERR(client) : -ENOTCONN; + + /* Exit cleanly if we’re stopping */ + if (kthread_should_stop()) break; - } - pr_warn("tcp_server: kernel_accept returned: %d - sleeping then retry\n", ret); + + /* Transient failure: back off a bit and retry */ + pr_debug("tcp_server: kaccept() error ptr=%p err=%ld; retrying\n", + client, err); msleep(100); continue; } - if (!newsock) { - pr_warn("tcp_server: kernel_accept returned NULL newsock\n"); - msleep(100); + pr_info("tcp_server: accepted client=%p\n", client); + + /* One recv then close (demo behavior) */ + buf = kmalloc(RECV_BUF_SZ, GFP_KERNEL); + if (!buf) { + pr_err("tcp_server: kmalloc failed\n"); + kclose(client); continue; } - pr_info("tcp_server: accepted newsock=%p newsock->sk=%p\n", newsock, newsock->sk); - - /* Receive a single message (blocking) and then close */ - { - char *buf = kmalloc(RECV_BUF_SZ, GFP_KERNEL); - if (!buf) { - pr_err("tcp_server: kmalloc failed\n"); - sock_release(newsock); - newsock = NULL; - continue; - } - - { - struct kvec iov = { .iov_base = buf, .iov_len = RECV_BUF_SZ - 1 }; - struct msghdr msg; - int n; - - memset(&msg, 0, sizeof(msg)); - n = kernel_recvmsg(newsock, &msg, &iov, 1, RECV_BUF_SZ - 1, 0); - if (n > 0) { - buf[n] = '\0'; - pr_info("tcp_server: received (%d bytes): %s\n", n, buf); - } else { - pr_info("tcp_server: kernel_recvmsg returned %d\n", n); - } - } - - kfree(buf); + n = krecv(client, buf, RECV_BUF_SZ - 1, 0); + if (n > 0) { + buf[n] = '\0'; + pr_info("tcp_server: received (%d bytes): %s\n", n, buf); + } else { + pr_info("tcp_server: krecv() returned %d\n", n); } - /* close connection */ - sock_release(newsock); - newsock = NULL; + kfree(buf); + kclose(client); } - /* cleanup listening socket */ + /* Cleanup listening socket */ if (listen_sock) { pr_info("tcp_server: closing listen socket %p\n", listen_sock); - sock_release(listen_sock); + kclose(listen_sock); listen_sock = NULL; } @@ -139,20 +135,18 @@ static int __init tcp_server_init(void) { static void __exit tcp_server_exit(void) { pr_info("tcp_server: Unloading\n"); - /* Shutdown listening socket to interrupt accept */ + /* Ask the listen socket to shut down so accept/recv unblocks */ if (listen_sock) { - kernel_sock_shutdown(listen_sock, SHUT_RDWR); + kshutdown(listen_sock, 2 /* SHUT_RDWR */); } - /* Stop the thread (waits for it to exit) */ if (server_thread) { kthread_stop(server_thread); server_thread = NULL; } - /* If still present, release listen socket (thread may have done it) */ if (listen_sock) { - sock_release(listen_sock); + kclose(listen_sock); listen_sock = NULL; } @@ -164,4 +158,4 @@ module_exit(tcp_server_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mephistolist"); -MODULE_DESCRIPTION("Kernel-space TCP server using ksocket"); +MODULE_DESCRIPTION("Kernel-space TCP server using ksocket wrapper API"); From 631467d034116f1826a8d694fb12fd114b93c42c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Wed, 20 Aug 2025 04:42:50 +0000 Subject: [PATCH 60/63] Update udp_server.c --- samples/udp/server/udp_server.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/samples/udp/server/udp_server.c b/samples/udp/server/udp_server.c index 50e93ec..c9afac0 100644 --- a/samples/udp/server/udp_server.c +++ b/samples/udp/server/udp_server.c @@ -4,20 +4,21 @@ #include #include #include -#include #include -#include +#include +#include #include "ksocket.h" int udp_server_fn(void *data); + static struct task_struct *server_thread; int udp_server_fn(void *data) { struct socket *sock; - struct sockaddr_in addr; - int ret; + struct sockaddr_in addr, src_addr; + int ret, len; char buffer[256]; - + sock = ksocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (!sock) { printk(KERN_ERR "UDP Server: Failed to create socket\n"); @@ -39,22 +40,20 @@ int udp_server_fn(void *data) { printk(KERN_INFO "UDP Server: Listening on port 4444\n"); while (!kthread_should_stop()) { - struct sockaddr_in src_addr; - int len = sizeof(src_addr); - memset(buffer, 0, sizeof(buffer)); + len = sizeof(src_addr); + ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&src_addr, &len); if (ret > 0) { buffer[ret] = '\0'; printk(KERN_INFO "UDP Server: Received '%s'\n", buffer); - // Send back acknowledgement - const char *reply = "ACK from UDP Server"; - ksendto(sock, (void *)reply, strlen(reply), 0, - (struct sockaddr *)&src_addr, sizeof(src_addr)); + ksendto(sock, "ACK from UDP Server", 19, 0, + (struct sockaddr *)&src_addr, sizeof(src_addr)); } - msleep(100); + + msleep(100); // this isn’t in your API, but it’s fine } kclose(sock); @@ -80,5 +79,5 @@ module_init(udp_server_init); module_exit(udp_server_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Simple UDP Server Example with ACK"); +MODULE_DESCRIPTION("Simple UDP Server Example using ksocket API"); MODULE_AUTHOR("Mephistolist"); From e0b1f606155ae0ec60b05cabc28a6b90d1c6033c Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Wed, 20 Aug 2025 04:43:58 +0000 Subject: [PATCH 61/63] Update udp_client.c --- samples/udp/client/udp_client.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/samples/udp/client/udp_client.c b/samples/udp/client/udp_client.c index c3c849f..a75e68d 100644 --- a/samples/udp/client/udp_client.c +++ b/samples/udp/client/udp_client.c @@ -4,13 +4,9 @@ #include #include #include -#include #include -#include -#include -#include -#include -#include +#include /* socket families, SOCK_STREAM */ +#include /* socket options */ #include "ksocket.h" #define SERVER_PORT 4444 @@ -35,7 +31,7 @@ static int udp_client_fn(void *data) { memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); - server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); + server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // <- use your exported symbol // Send message ret = ksendto(sock, (void *)message, strlen(message), 0, @@ -48,13 +44,13 @@ static int udp_client_fn(void *data) { printk(KERN_INFO "[udp_client] Sent: %s\n", message); - // Non-blocking receive with timeout + // Try receive (non-blocking with manual timeout loop) { unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); int addr_len = sizeof(server_addr); ret = -EAGAIN; - while (time_before(jiffies, timeout)) { + while (time_before(jiffies, timeout) && !kthread_should_stop()) { ret = krecvfrom(sock, buffer, sizeof(buffer) - 1, MSG_DONTWAIT, (struct sockaddr *)&server_addr, &addr_len); if (ret >= 0) { @@ -66,7 +62,7 @@ static int udp_client_fn(void *data) { } if (ret < 0) - printk(KERN_WARNING "[udp_client] No response from server (timeout or unreachable)\n"); + printk(KERN_WARNING "[udp_client] No response from server (timeout)\n"); } kclose(sock); @@ -94,4 +90,4 @@ module_exit(udp_client_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mephistolist"); -MODULE_DESCRIPTION("Simple UDP Client using ksocket"); +MODULE_DESCRIPTION("Simple UDP Client using ksocket API"); From 8e0ff790570312053a87f334c0ff732e897185ef Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Wed, 20 Aug 2025 04:44:24 +0000 Subject: [PATCH 62/63] Update udp_client.c --- samples/udp/client/udp_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/udp/client/udp_client.c b/samples/udp/client/udp_client.c index a75e68d..3101851 100644 --- a/samples/udp/client/udp_client.c +++ b/samples/udp/client/udp_client.c @@ -5,8 +5,8 @@ #include #include #include -#include /* socket families, SOCK_STREAM */ -#include /* socket options */ +#include +#include #include "ksocket.h" #define SERVER_PORT 4444 From b5c4d1b412705b1acf1262d4141657d84ec4a641 Mon Sep 17 00:00:00 2001 From: mephistolist <49227141+mephistolist@users.noreply.github.com> Date: Wed, 20 Aug 2025 04:45:07 +0000 Subject: [PATCH 63/63] Update tcp_server.c --- samples/tcp/server/tcp_server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/tcp/server/tcp_server.c b/samples/tcp/server/tcp_server.c index 63a3cce..21227c0 100644 --- a/samples/tcp/server/tcp_server.c +++ b/samples/tcp/server/tcp_server.c @@ -6,9 +6,9 @@ #include #include #include -#include /* socket families, SOCK_STREAM */ -#include /* socket options */ -#include "ksocket.h" /* <-- your wrapper API */ +#include +#include +#include "ksocket.h" #define SERVER_PORT 12345 #define BACKLOG 5