diff --git a/Kernel/Makefile b/Kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bf36e7f57193878db21d084a61da47abe669c9a5 --- /dev/null +++ b/Kernel/Makefile @@ -0,0 +1,7 @@ +obj-m := kernel_M.o +KVERSION = $(shell uname -r) +all: + make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean \ No newline at end of file diff --git a/Kernel/kernel_M.c b/Kernel/kernel_M.c new file mode 100644 index 0000000000000000000000000000000000000000..1e92a581657cdc84c48f2e1ed25c2593882b1607 --- /dev/null +++ b/Kernel/kernel_M.c @@ -0,0 +1,196 @@ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fs.h> // For file_operations +#include <linux/uaccess.h> // For copy_from_user +#include <linux/cdev.h> // For cdev +#include <linux/device.h> // For device_create, class_create +#include <linux/slab.h> // For kmalloc, kfree + +#define DEVICE_NAME "packet_receiver" +#define CLASS_NAME "packet_class" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Me :)"); +MODULE_DESCRIPTION("A kernel module to receive packets from userspace."); +MODULE_VERSION("1.0"); + +// Structure to hold our packet data +struct packet_data { + int sender_id; + int value_id_1; + int value_1; + int value_id_2; + int value_2; +}; + +// The size of the receive buffer +#define RECV_BUF_SIZE 128 + +// Global variables for device number, class, device. +static dev_t dev_number; +static struct class *packet_class = NULL; +static struct cdev packet_cdev; + +// This buffer will temporarily store data from userspace +static char *recv_buffer; + +// Forward declarations for file operations +static int packet_open(struct inode *inode, struct file *file); //not used +static int packet_release(struct inode *inode, struct file *file); //not used +static ssize_t packet_read(struct file *filp, char __user *buf, size_t len, loff_t *offset); //not used +static ssize_t packet_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset); + +// File operations structure +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = packet_open, //not used + .read = packet_read, //not used + .write = packet_write, + .release = packet_release, //not used +}; + +// ====================== Device Open ====================== +static int packet_open(struct inode *inode, struct file *file) { + printk(KERN_INFO "packet_receiver: Device opened.\n"); + return 0; +} + +// ====================== Device Read ====================== +static ssize_t packet_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) { + printk(KERN_INFO "packet_receiver: Read called.\n"); + return 0; +} + +// ====================== Device Write ====================== +static ssize_t packet_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) { + // Bound the incoming size to the size of the buffer + size_t to_copy = min(len, (size_t)RECV_BUF_SIZE - 1); + + // Clear the buffer before copying data into it (for safety) + memset(recv_buffer, 0, RECV_BUF_SIZE); + + // Copy data from user space into recv_buffer + if (copy_from_user(recv_buffer, buf, to_copy) != 0) { + printk(KERN_ERR "packet_receiver: copy_from_user failed.\n"); + return -EFAULT; + } + + // Ensure null-termination + recv_buffer[to_copy] = '\0'; + + // Placeholders for the fields: + struct packet_data p_data; + p_data.sender_id = -1; + p_data.value_id_1 = -1; + p_data.value_1 = -1; + p_data.value_id_2 = -1; + p_data.value_2 = -1; + + // Example format: + // "SENDER=1 ID1=100 VAL1=222 ID2=101 VAL2=333" + // "SENDER=10 VID1=11 VAL1=100 VID2=12 VAL2=200" + + sscanf(recv_buffer, "SENDER=%d VID1=%d VAL1=%d VID2=%d VAL2=%d", + &p_data.sender_id, + &p_data.value_id_1, + &p_data.value_1, + &p_data.value_id_2, + &p_data.value_2); + + // Print the received packet data + printk(KERN_INFO "packet_receiver: Received packet -> " + "sender=%d, valID1=%d, val1=%d, valID2=%d, val2=%d\n", + p_data.sender_id, + p_data.value_id_1, p_data.value_1, + p_data.value_id_2, p_data.value_2); + + // Return the number of bytes written + return len; +} + +// ====================== Device Release ====================== +static int packet_release(struct inode *inode, struct file *file) { + printk(KERN_INFO "packet_receiver: Device closed.\n"); + return 0; +} + +// ====================== Module Init ====================== +static int __init packet_init(void) { + int ret; + + // Allocate a device number dynamically + ret = alloc_chrdev_region(&dev_number, 0, 1, DEVICE_NAME); + if (ret < 0) { + printk(KERN_ERR "packet_receiver: Failed to allocate major/minor.\n"); + return ret; + } + printk(KERN_INFO "packet_receiver: Registered with major=%d, minor=%d\n", + MAJOR(dev_number), MINOR(dev_number)); + + // Initialize the cdev structure + cdev_init(&packet_cdev, &fops); + packet_cdev.owner = THIS_MODULE; + + // Add the cdev to the kernel + ret = cdev_add(&packet_cdev, dev_number, 1); + if (ret < 0) { + printk(KERN_ERR "packet_receiver: Unable to add cdev.\n"); + unregister_chrdev_region(dev_number, 1); + return ret; + } + + // Create a class for udev + packet_class = class_create(CLASS_NAME); + if (IS_ERR(packet_class)) { + printk(KERN_ERR "packet_receiver: Failed to create class.\n"); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return PTR_ERR(packet_class); + } + + // Create a device node /dev/packet_receiver + if (IS_ERR(device_create(packet_class, NULL, dev_number, NULL, DEVICE_NAME))) { + printk(KERN_ERR "packet_receiver: Failed to create device.\n"); + class_destroy(packet_class); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return -1; + } + + // Allocate memory for receive buffer + recv_buffer = kmalloc(RECV_BUF_SIZE, GFP_KERNEL); + if (!recv_buffer) { + printk(KERN_ERR "packet_receiver: Failed to allocate recv_buffer.\n"); + device_destroy(packet_class, dev_number); + class_destroy(packet_class); + cdev_del(&packet_cdev); + unregister_chrdev_region(dev_number, 1); + return -ENOMEM; + } + + printk(KERN_INFO "packet_receiver: Module loaded.\n"); + return 0; +} + +// ====================== Module Exit ====================== +static void __exit packet_exit(void) { + // Free recv_buffer + if (recv_buffer) { + kfree(recv_buffer); + } + + // Remove device node + device_destroy(packet_class, dev_number); + // Destroy class + class_destroy(packet_class); + // Delete cdev + cdev_del(&packet_cdev); + // Free device numbers + unregister_chrdev_region(dev_number, 1); + + printk(KERN_INFO "packet_receiver: Module unloaded.\n"); +} + +module_init(packet_init); +module_exit(packet_exit);