Linux - 模組編程初試

來源:互聯網
上載者:User

標籤:

  電腦網路的課程設計要做防火牆,老師沒有限制在什麼系統上面做,所以決定在Linux上實現。找了一下相關的資料,發現其實Linux有提供Netfilter/Iptables,為使用者提供防火牆的功能,稍微看了一下,使用Iptables能夠很方便地配置使用者想要的防火牆,但是好像只能做過濾、資料報修改以及網路位址轉譯,好像不能做擷取其中資訊的功能,而且看了一下網上其他人的提問或者部落格,好像想做類似的功能還是需要直接使用Netfilter。而如果想要使用Netfiler的話,需要編寫hook函數,這個過程中不得不避免要編寫模組。所以這裡記錄一下我在這個過程中做的一些嘗試以及遇到的問題。

 

  使用的平台:Ubuntu 14.10

  核心版本: 3.16.0-23-generic  (這個很重要啊,不用的核心可能函數都是不一樣的,網上的大部分教程用的核心版本都是2.6)

 

2015.4.23

  第一次我是編寫一個hello world,在載入模組的時候以及移除模組的時候各輸出一次,這裡做的都是跟著網上的教程寫的。

代碼如下:

 1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/init.h> 4  5  6 static int __init lkp_init(void); 7 static int __exit lkp_exit(void); 8  9 static int __init lkp_init(void){10         printk("<1>Hello,world!\n");11         return 0;12 }13 14 static int __exit lkp_exit(void){15         printk("<2>Hello,world!\n");16         return 0;17 }18 19 module_init(lkp_init);20 module_exit(lkp_exit);

Makefile:

 1 ifneq ($(KERNELRELEASE),) 2 mymodule-objs:=hello.c 3 obj-m += hello.o 4  5 else 6 PWD := $(shell pwd) 7 KVER := $(shell uname -r) 8 KDIR := /lib/modules/$(KVER)/build 9 10 all:11     $(MAKE) -C $(KDIR) M=$(PWD)12 clean:13     rm -rf *.o *.mod.c *.ko *.symvers *order *.markers *-14 endif

  make一次以後然後載入模組: sudo insmod hello.ko

  使用指令dmesg能夠查看到載入的時候的輸出。

  移除模組: sudo rmmod hello.ko

  再次使用dmesg能夠查看到移除的時候的輸出。

  這裡這個Makefile是怎麼執行的,為什麼需要使用dmesg來查看輸出的問題我暫時先不寫,因為這些在網上都能找到而且能夠比較清楚地解釋,我打算寫的是一些我遇到的問題。

 

2015.4.26

  開始編寫與Netfilter有關的函數,首先寫的這個也是按照別人的教程給的例子寫的程式。寫一個鉤子掛載到 LOCAL_OUT上。然後每隔四個發出去的資料包就攔截下下一個資料包。

代碼如下:

 1 #ifndef __KERNEL__ 2 #define __KERNEL__ 3 #endif 4 #ifndef MODULE 5 #define MODULE 6 #endif 7 #include <linux/module.h> 8 #include <linux/kernel.h> 9 #include <linux/netfilter.h>10 #include <linux/netfilter_ipv4.h>11 12 static int count=0;13 14 static unsigned int func(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){15     count=(count+1)%5;16     if(count==0){17         return NF_DROP;18     }19     return NF_ACCEPT;20 }21 22 static struct nf_hook_ops nfho;23 24 static int __init myhook_init(void){25     nfho.hook = func;26     nfho.owner = THIS_MODULE;27     nfho.pf = PF_INET;28     nfho.hooknum = NF_INET_LOCAL_OUT;29     nfho.priority = NF_IP_PRI_FIRST;30     return  nf_register_hook(&nfho);31 }32 33 static void __exit myhook_fini(void){34     nf_unregister_hook(&nfho);35 }36 37 module_init(myhook_init);38 module_exit(myhook_fini);

Makefile:

 1 ifneq ($(KERNELRELEASE),) 2 mymodule-objs:=test0.c 3 obj-m += test0.o 4  5 else 6 PWD := $(shell pwd) 7 KVER := $(shell uname -r) 8 KDIR := /lib/modules/$(KVER)/build 9 10 all:11     $(MAKE) -C $(KDIR) M=$(PWD) modules12 clean:13     rm -rf *.o *.mod.c *.ko *.symvers *order *.markers *-14 endif

   問題來了,如果是按照網上的其他例子來寫的話,make的時候就會說NF_IP_LOCAL_OUT找不到。當然還有一個警告說nfho.hook = func有問題,這個可能要看看怎樣寫它才會不警告,這裡不理這個警告沒有問題。我們繼續說NF_IP_LOCAL_OUT,開啟儲存所有標頭檔的目錄,發現這個宏定義有啊,就在linux/netfilter_ipv4.h裡面,是從uapi/linux/netfilter_ipv4.h包含進來的,但是這裡又有個問題,它是被ifndef __KERNEL__  ``` endif 包住了,所以它編譯的時候沒有包含進去,如下面的代碼:

 1 #ifndef __KERNEL__ 2  3 #include <limits.h> /* for INT_MIN, INT_MAX */ 4  5 /* IP Cache bits. */ 6 /* Src IP address. */ 7 #define NFC_IP_SRC        0x0001 8 /* Dest IP address. */ 9 #define NFC_IP_DST        0x000210 /* Input device. */11 #define NFC_IP_IF_IN        0x000412 /* Output device. */13 #define NFC_IP_IF_OUT        0x000814 /* TOS. */15 #define NFC_IP_TOS        0x001016 /* Protocol. */17 #define NFC_IP_PROTO        0x002018 /* IP options. */19 #define NFC_IP_OPTIONS        0x004020 /* Frag & flags. */21 #define NFC_IP_FRAG        0x008022 23 /* Per-protocol information: only matters if proto match. */24 /* TCP flags. */25 #define NFC_IP_TCPFLAGS        0x010026 /* Source port. */27 #define NFC_IP_SRC_PT        0x020028 /* Dest port. */29 #define NFC_IP_DST_PT        0x040030 /* Something else about the proto */31 #define NFC_IP_PROTO_UNKNOWN    0x200032 33 /* IP Hooks */34 /* After promisc drops, checksum checks. */35 #define NF_IP_PRE_ROUTING    036 /* If the packet is destined for this box. */37 #define NF_IP_LOCAL_IN        138 /* If the packet is destined for another interface. */39 #define NF_IP_FORWARD        240 /* Packets coming from a local process. */41 #define NF_IP_LOCAL_OUT        342 /* Packets about to hit the wire. */43 #define NF_IP_POST_ROUTING    444 #define NF_IP_NUMHOOKS        545 #endif /* ! __KERNEL__ */

  原因:在2.6.22以及以後的核心中,NF_IP_PRE_ROUTING以及NF_IP6_PRE_ROUTING都被放在了使用者態,而在核心態編程必須統一使用NF_INET_PRE_ROUTING。

  所以解決的辦法就是使用NF_INET_XXXXXXX來代替相關的宏就行了。

  這裡坑了我比較長的時間。

  修改了以後再編譯一次,然後載入模組以後,ping一下,然後就出現效果了,每五個包就會有一個發不出去。

 

 

 

 

 

/******************************************************************************************************************************************************************************************/

持續更新...

Linux - 模組編程初試

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.