Skip to content

CE408-OSL/Experiment10

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

آزمایش ۱۰ - آشنایی با درایورها

  • گروه شماره ۲۵
    • معین آعلی - ۴۰۱۱۰۵۵۶۱
    • ثمین اکبری - ۴۰۱۱۰۵۵۹۴

آزمایش اول

کد درایور:

#include <linux/module.h>   
#include <linux/kernel.h>   
#include <linux/init.h>     

static int __init hello_init(void) {
    printk(KERN_INFO "Hello\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye\n");
}

module_init(hello_init); 
module_exit(hello_exit);  

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Moeein Aali");
MODULE_DESCRIPTION("Hello World Linux kernel module");

ابتدا دستور Make را اجرا می‌کنیم و سپس:

نتیجه‌ی اجرا:

توضیحات:

#include <linux/module.h>: کتابخانه اصلی برای نوشتن ماژول کرنل.

#include <linux/kernel.h>: شامل توابعی مثل printk.

#include <linux/init.h>: برای ماکروهای __init و __exit.

hello_init: هنگام بارگذاری ماژول توسط دستور insmod اجرا شده و پیام "Hello" چاپ می‌کند.

hello_exit: هنگام حذف ماژول با rmmod اجرا شده و پیام "Goodbye" چاپ می‌کند.

printk: مشابه printf در فضای کرنل، با سطح اهمیت (KERN_INFO).

module_init و module_exit: معرفی توابع ورودی و خروجی ماژول.

متادیتا مثل MODULE_LICENSE، MODULE_AUTHOR و MODULE_DESCRIPTION: اطلاعات ماژول.

نیازمندی اجرایی:

sudo apt-get install build-essential linux-headers-$(uname -r)

البته این را در آزمایش‌های قبل نصب کرده‌ایم و نیازی به اجرای آن نبود...

آزمایش دوم

کد درایور:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/time.h>
#include <linux/string.h>

#define LOG_FILE "/var/log/netmon.log"

static struct nf_hook_ops nfho_in;
static struct nf_hook_ops nfho_out;
static struct file *log_file = NULL;
static loff_t log_pos = 0;

static char* get_protocol_name(unsigned int protocol) {
    switch(protocol) {
        case IPPROTO_TCP: return "TCP";
        case IPPROTO_UDP: return "UDP";
        case IPPROTO_ICMP: return "ICMP";
        default: return "OTHER";
    }
}

static void log_packet(const struct sk_buff *skb, const char *direction) {
    struct iphdr *ip_header;
    struct tcphdr *tcp_header;
    struct udphdr *udp_header;
    char log_entry[256];
    struct timespec64 ts;
    int len = 0;

    if (!skb || !log_file) return;

    ip_header = ip_hdr(skb);
    if (!ip_header) return;

    ktime_get_real_ts64(&ts);

    len = snprintf(log_entry, sizeof(log_entry),
                  "[%lld.%09ld] %s %pI4:%d -> %pI4:%d %s len=%d\n",
                  (long long)ts.tv_sec, ts.tv_nsec,
                  direction,
                  &ip_header->saddr, ntohs(ip_header->saddr),
                  &ip_header->daddr, ntohs(ip_header->daddr),
                  get_protocol_name(ip_header->protocol),
                  ntohs(ip_header->tot_len));

    if (len > 0) {
        kernel_write(log_file, log_entry, len, &log_pos);
    }
}

static unsigned int hook_func_in(void *priv, struct sk_buff *skb,
                               const struct nf_hook_state *state) {
    log_packet(skb, "IN");
    return NF_ACCEPT;
}

static unsigned int hook_func_out(void *priv, struct sk_buff *skb,
                                const struct nf_hook_state *state) {
    log_packet(skb, "OUT");
    return NF_ACCEPT;
}

static int __init netmon_init(void) {
    log_file = filp_open(LOG_FILE, O_WRONLY|O_CREAT|O_APPEND, 0644);
    if (IS_ERR(log_file)) {
        printk(KERN_ERR "Failed to open log file\n");
        return PTR_ERR(log_file);
    }

    nfho_in.hook = hook_func_in;
    nfho_in.hooknum = NF_INET_PRE_ROUTING;
    nfho_in.pf = PF_INET;
    nfho_in.priority = NF_IP_PRI_FIRST;
    nf_register_net_hook(&init_net, &nfho_in);

    nfho_out.hook = hook_func_out;
    nfho_out.hooknum = NF_INET_POST_ROUTING;
    nfho_out.pf = PF_INET;
    nfho_out.priority = NF_IP_PRI_FIRST;
    nf_register_net_hook(&init_net, &nfho_out);

    printk(KERN_INFO "Network monitor loaded\n");
    return 0;
}

static void __exit netmon_exit(void) {
    nf_unregister_net_hook(&init_net, &nfho_in);
    nf_unregister_net_hook(&init_net, &nfho_out);

    if (log_file && !IS_ERR(log_file)) {
        filp_close(log_file, NULL);
    }

    printk(KERN_INFO "Network monitor unloaded\n");
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Moeein");
MODULE_DESCRIPTION("Network monitoring");

module_init(netmon_init);
module_exit(netmon_exit);

شیوه عملکرد این درایور به این صورت است که در تابع init، ماژول ابتدا فایل لاگ خود را با پرچم‌های O_WRONLY، O_CREATE و O_APPEND باز می‌کند تا امکان نوشتن در انتهای فایل و در صورت لزوم ایجاد آن فراهم شود. سپس با بهره‌گیری از تابع nf_register_net_hook، یک قلاب روی namespace شبکه قرار می‌دهیم. در اینجا init_net همان namespace اصلی است که تمامی ترافیک از آن عبور می‌کند. بنابراین می‌توانیم ترافیک ورودی و خروجی را به تابع log_packet هدایت کنیم. در پایان، این تابع داده‌های مهمی مانند زمان ارسال بسته، آدرس‌های مبدأ و مقصد، نوع پروتکل و طول پیام را با استفاده از snprintf قالب‌بندی کرده و در فایل موردنظر ذخیره می‌کند.

نتیجه اجرا:

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published