歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核分析 - 網絡[七]:NetFilter

Linux內核分析 - 網絡[七]:NetFilter

日期:2017/3/1 11:09:18   编辑:Linux內核
內核版本:2.6.34

NetFilter在2.4.x內核中引入,成為linux平台下進行網絡應用的主要擴展,不僅包括防火牆的實現,還包括報文的處理(如報文加密、報文分類統計等)等。

NetFilter數據結構 勾子struct nf_hook_ops[net\filter\core.c]
  1. struct nf_hook_ops {
  2. struct list_head list;
  3. /* User fills in from here down. */
  4. nf_hookfn *hook;
  5. struct module *owner;
  6. u_int8_t pf;
  7. unsigned int hooknum;
  8. /* Hooks are ordered in ascending priority. */
  9. int priority;
  10. };
成員list用於鏈入全局勾子數組nf_hooks中,它一定在第一位,保證&nf_hook_ops->list的值與&nf_hook_ops相同,稍後在使用時會用到這一技巧;
成員hook即用戶定義的勾子函數;owner表示注冊這個勾子函數的模塊,因為netfilter是內核空間的,所以一般為模塊來完成勾子函數注冊;pf與hooknum一起索引到特定協議特定編號的勾子函數隊列,用於索引nf_hooks;priority決定在同一隊列(pf與hooknum相同)的順序,priority越小則排列越靠前。
struct nf_hook_ops只是存儲勾子的數據結構,而真正存儲這些勾子供協議棧調用的是nf_hooks,從定義可以看出,它其實就是二維數組的鏈表。
struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; [net\filter\core.c]
其中NFPROTO_NUMPROTO表示勾子關聯的協議,可取值:
  1. enum {
  2. NFPROTO_UNSPEC = 0,
  3. NFPROTO_IPV4 = 2,
  4. NFPROTO_ARP = 3,
  5. NFPROTO_BRIDGE = 7,
  6. NFPROTO_IPV6 = 10,
  7. NFPROTO_DECNET = 12,
  8. NFPROTO_NUMPROTO,
  9. };
NF_MAX_HOOKS表示勾子應用的位置,可選值在每個協議模塊內部定義,這些值代表了勾子函數在協議流程中應用的位置(稍後會以bridge為例詳細說明),大致上都有以下值:
  1. NF_XXX_PRE_ROUTING,
  2. NF_XXX_LOCAL_IN,
  3. NF_XXX_FORWARD,
  4. NF_XXX_LOCAL_OUT,
  5. NF_XXX_POST_ROUTING,
  6. NF_XXX_NUMHOOKS

NetFilter注冊
在了解了nf_hook_ops和nf_hooks後,來看下如何操作nf_hooks中的元素。
nf_register_hook()將nf_hook_ops注冊到nf_hooks中:
  1. int nf_register_hook(struct nf_hook_ops *reg)
  2. {
  3. struct nf_hook_ops *elem;
  4. int err;
  5. err = mutex_lock_interruptible(&nf_hook_mutex);
  6. if (err < 0)
  7. return err;
  8. list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
  9. if (reg->priority < elem->priority)
  10. break;
  11. }
  12. list_add_rcu(?->list, elem->list.prev);
  13. mutex_unlock(&nf_hook_mutex);
  14. return 0;
  15. }
這個函數很簡單,從指定pf&hooknum的nf_hooks隊列遍歷,按priority從小到大順序,將reg插入相應位置,完成勾子函數的注冊。

nf_unregister_hook()將nf_hook_ops從nf_hooks中注銷掉:
  1. void nf_unregister_hook(struct nf_hook_ops *reg)
  2. {
  3. mutex_lock(&nf_hook_mutex);
  4. list_del_rcu(?->list);
  5. mutex_unlock(&nf_hook_mutex);
  6. synchronize_net();
  7. }
這個函數更簡單,從nf_hooks中刪除reg。
內核同時還提供了nf_register_hooks()和nf_unregister_hooks(),將reg重復注冊n次或將reg從nf_hooks中注銷n次。當勾子函數注冊完成後,nf_hooks的結構如圖所示:

Copyright © Linux教程網 All Rights Reserved