网络协议的初始化dev_add_pack

转自:http://blog.csdn.net/dianhuiren/article/details/6920380
  1. 在 数据包接收过程的那篇笔记中可以知道,在数据包的处理函数netif_receive_skb中,会先看ptype_all中是否有注册的协议,如果有, 则调用相应的处理函数,然后再到ptype_base中,找到合适的协议,将skb发送到相关协议的处理函数.比如ip协议(ip_rcv)或者 arp(arp_rcv)等等.此篇笔记讲的是有关ptype_all和ptype_base的相关知识点.  
  2.   
  3. ptype_base和ptype_all在内核中存储的情况如下图:  
  4.   
  5.   
  6.   
  7. 可以看到,ptype_base为一个hash表,而ptype_all为一个双向链表.每一个里面注册的协议都用一个struct packet_type表示.  
  8.   
  9. struct packet_type   
  10.  
  11.     unsigned short        type;      
  12.     struct net_device     *dev;     
  13.     int            (*func) (struct sk_buff *, struct net_device *,  
  14.                      struct packet_type *);  
  15.     void            *data;      
  16.     struct packet_type    *next;  
  17. };  
  18. 其中需要注意的是dev参数,此参数表明了协议只处理来自dev指向device的数据,当dev=NULL时,表示该协议处理来自所有device的数据.这样,当注册自己的协议时,就可以指定自己想要监听或者接收的device.  
  19. 其中注册和注销协议的函数为:  
  20. dev_add_pack(...)和dev_remove_pack(...)  
  21. 这两个函数很简单,分别如下:  
  22. void dev_add_pack(struct packet_type *pt)  
  23.  
  24.     int hash;  
  25.     br_write_lock_bh(BR_NETPROTO_LOCK);  
  26. #ifdef CONFIG_NET_FASTROUTE  
  27.       
  28.     if ((pt->data) && ((int)(pt->data)!=1))  
  29.         netdev_fastroute_obstacles++;  
  30.         dev_clear_fastroute(pt->dev);  
  31.      
  32. #endif  
  33.     if (pt->type == htons(ETH_P_ALL))  
  34.         netdev_nit++;  
  35.         pt->next=ptype_all;  
  36.         ptype_all=pt;  
  37.     else  
  38.         hash=ntohs(pt->type)&15;  
  39.         pt->next ptype_base[hash];  
  40.         ptype_base[hash] pt;  
  41.      
  42.     br_write_unlock_bh(BR_NETPROTO_LOCK);  
  43.  
  44. 此函数判断协议类型,然后加到ptype_base或者ptype_all中.  
  45. void dev_remove_pack(struct packet_type *pt)  
  46.  
  47.     struct packet_type **pt1;  
  48.     br_write_lock_bh(BR_NETPROTO_LOCK);  
  49.     if (pt->type == htons(ETH_P_ALL))  
  50.         netdev_nit--;  
  51.         pt1=&ptype_all;  
  52.     else  
  53.         pt1=&ptype_base[ntohs(pt->type)&15];  
  54.      
  55.     for (; (*pt1) != NULL; pt1 &((*pt1)->next))  
  56.         if (pt == (*pt1))  
  57.             *pt1 pt->next;  
  58. #ifdef CONFIG_NET_FASTROUTE  
  59.             if (pt->data)  
  60.                 netdev_fastroute_obstacles--;  
  61. #endif  
  62.             br_write_unlock_bh(BR_NETPROTO_LOCK);  
  63.             return;  
  64.          
  65.      
  66.     br_write_unlock_bh(BR_NETPROTO_LOCK);  
  67.     printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);  
  68.  
  69. 此函数也很简单,只是把协议从相关的链表中移除.  
  70. 下面以ip协议为例子来看看相关的实现:  
  71. ip协议结构体的定义如下:  
  72. static struct packet_type ip_packet_type  
  73.  
  74.     __constant_htons(ETH_P_IP),  
  75.     NULL,      
  76.     ip_rcv,  
  77.     (void*)1,  
  78.     NULL,  
  79. };  
  80. 当ipv4协议栈初始化时,会调用ip_init.之后,所有协议类型为ETH_P_IP的包都会交由ip_rcv处理.代码如下:  
  81. void __init ip_init(void)  
  82.  
  83.     dev_add_pack(&ip_packet_type);  
  84.     ip_rt_init();  
  85.     inet_initpeers();  
  86. #ifdef CONFIG_IP_MULTICAST  
  87.     proc_net_create("igmp", 0, ip_mc_procinfo);  
  88. #endif  
  89.  
  90. 这样在系统启动之后,ip协议便被注册到ptype_base链表中,相应的处理函数为ip_rcv.  
  91. arp协议和其他类型的协议(在ptype_base或者ptype_all中的)的执行过程同理.  
  92. 本人初学网络,水平很菜,如有错误,希望看到的朋友们及时指出,不胜感激.  
  93. ps1: 记得刚来实验室的时候,做的截包模块的第一种方法是用的netfilter,第二种方法主要就是用到的这块知识.现在总结起来,觉得还算简单,当初却用了 很长时间,想想,真是难者不会,会者不难啊.今天看书的时候,好像又发现了另外一种方法可以实现我的要求,记录在ps2上.  
  94. ps2: 在数据链路层截包的另一种方法:用PF_PACKET socket type.linux可以用此类型套节字直接从链路层截获或者注入数据.发送数据 时,直接发送到dev_queue_xmit.而接收函数时,可以在数据包通过路由之前截获到.如tcpdump和Ethereal都是用到了此套接字. 那么总结起来可以看出,截获数据包至少可以有三种方法实现,第一种的netfilter是在协议栈中截获数据包,而利用ptype_all或者 ptype_base和后面这种套节字的方法是在链路层截获数据包. 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值