内核使用dev_add_pack一例(scu.edu difeijing)

下面的东西,假定你比较了解Linux内核的网络部分和LKM的一些 
 机制. 
   前面那篇kernel sniffer其实就是对函数dev_add_pack()的使用,这里 
 再给一个内核中使用dev_add_pack()的例子,说出来大家应该都知道, 
 就是SOCK_PACKET类型的socket. 
 SOCK_PACKET的套接口能抓住各种类型的包,那它是怎么实现的呢? 
 它在创建的时候用SOCK_PACKET这个参数告诉Linux,然后Linux会 
 有一些特别的操作,好了,start here. 
   
   
   从创建时开始,那就是sys_socketcall了,所有的跟socket有关的 
 操作都是用系统调用sys_socketcall. 
 OK,sys_socketcall()在socket.c中, 
 asmlinkage int sys_socketcall(int call, unsigned long *args) 
 在判断操作的switch中看到下面这句话, 
 case SYS_SOCKET: 
                 err = sys_socket(a0,a1,a[2]); 
                 break; 
 那就去看看sys_socket()吧,它也在socket.c里。 
 asmlinkage int sys_socket(int family, int type, int protocol) 
 下面这句,retval = sock_create(family, type, protocol, &sock), 
 原来它也是用别的函数呀,继续。sock_create()也在socket.c里面, 
 int sock_create(int family, int type, int protocol, struct socket 
 **res) 
 看下面的语句, 
 if ((i = net_families[family]->create(sock, protocol)) < 0) 
 { 
         sock_release(sock); 
         return i; 
 } 
 net_families是个全局变量,其定义为 
 /* 
  *      The protocol list. Each protocol is registered in here. 
  */ 
   
 struct net_proto_family *net_families[NPROTO]; 
 你注意到上面的注释了么?原来大家集中到一起了。每个协议族都会到 
 这个数组里注册信息,包括起创建例程,。。,下面是对结构 
 struct net_proto_family的定义: 
 struct net_proto_family 
 { 
         int     family; 
         int     (*create)(struct socket *sock, int protocol); 
         /* These are counters for the number of different methods of 
            each we support */ 
         short   authentication; 
         short   encryption; 
         short   encrypt_net; 
 }; 
 family值定义在socket.h中,象PF_INET,PF_IPX,IP_PACKET,...... 
 好了,现在知道要找的目标了,就是PF_PACKET协议族在net_families 
 里注册的创建例程,我找,找,找...终于找到了对net_families操作的 
 地方了,也是在socket.c中,函数ock_register()中,很简单的操作, 
 int sock_register(struct net_proto_family *ops) 
 { 
         if (ops->family >= NPROTO) { 
                 printk(KERN_CRIT "protocol %d >= NPROTO(%d)/n", ops->fami 
 ly, NPROTO); 
   
                 return -ENOBUFS; 
         } 
         net_families[ops->family]=ops; 
         return 0; 
 } 
 从这里可以看得出来这是各协议族用来注册的,好,查一下有什么地方用了这个 
 喊数。果然不出所料,用这个函数的文件是下面这些, 
 Af_ax25.c (f:/linux-2.2.12/net/ax25):   sock_register(&ax25_family_ops); 
 Af_inet.c (f:/linux-2.2.12/net/ipv4):   (void) 
 sock_register(&inet_family_ops); 
 Af_inet6.c (f:/linux-2.2.12/net/ipv6):  (void) 
 sock_register(&inet6_family_ops); 
 Af_ipx.c (f:/linux-2.2.12/net/ipx):     (void) 
 sock_register(&ipx_family_ops); 
 Af_irda.c (f:/linux-2.2.12/net/irda):   sock_register(&irda_family_ops); 
 Af_netlink.c (f:/linux-2.2.12/net/netlink): 
         sock_register(&netlink_family_ops); 
 Af_netrom.c (f:/linux-2.2.12/net/netrom): 
         sock_register(&nr_family_ops); 
 Af_packet.c (f:/linux-2.2.12/net/packet): 
         sock_register(&packet_family_ops); 
 Af_rose.c (f:/linux-2.2.12/net/rose):   sock_register(&rose_family_ops); 
 Af_unix.c (f:/linux-2.2.12/net/unix):   sock_register(&unix_family_ops); 
 Af_x25.c (f:/linux-2.2.12/net/x25):     sock_register(&x25_family_ops); 
 Ddp.c (f:/linux-2.2.12/net/appletalk):  (void) 
 sock_register(&atalk_family_ops); 
 Econet.c (f:/linux-2.2.12/net/econet): 
         sock_register(&econet_family_ops); 
 现在清楚了,各协议族都用sock_register()来注册一下自己,我们关心的是 
 packet,所以 
 去看文件af_packet.c. 
 int init_module(void) 
 { 
         sock_register(&packet_family_ops); 
         register_netdevice_notifier(&packet_netdev_notifier); 
         return 0; 
 } 
 继续向下,看看packet_family_ops的内容,它也是在af_packet.c里。 
 static struct net_proto_family packet_family_ops = 
 { 
         PF_PACKET, 
         packet_create 
 }; 
 前面有struct net_proto_family的定义,我们知道packet_family_ops 
 的family值为PF_PACKET,创建例程为packet_create,马上就要切入正题了。 
 packete_create()也是定义在af_packet.c中,这个函数还有点长,这里就没必要 
 全部 
 贴出来了。它前面一大段,是一些细节,权限检查,模块计数增加,对struct 
 sock和 
 struct socket的一些域的填充,下面几句才是我们关心的。 
 /* 
  *      Attach a protocol block 
 */ 
         struct sock *sk; 
         sk->protinfo.af_packet->prot_hook.func = packet_rcv; 
             sk->protinfo.af_packet->prot_hook.data = (void *)sk; 
         if (protocol) { 
                 sk->protinfo.af_packet->prot_hook.type = protocol; 
                 dev_add_pack(&sk->protinfo.af_packet->prot_hook); 
                 sk->protinfo.af_packet->running = 1; 
         } 
   
 看见用dev_add_pack那句了吧! 
 其实SOCK_PACKET的实现就是用dev_add_pack()来的,我们现在还可以 
 知道它用的处理包的函数是packet_rcv(),hehe. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值