下面的東西,假定你比較瞭解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.