下面的东西,假定你比较了解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.
内核使用dev_add_pack一例(scu.edu difeijing)
最新推荐文章于 2023-03-01 16:17:09 发布