免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
ptype_base和ptype_all理解,netid_receive_skb()函數(shù)注解

在數(shù)據(jù)包接收過(guò)程的那篇筆記中可以知道,在數(shù)據(jù)包的處理函數(shù)netif_receive_skb中,會(huì)先看ptype_all中是否有注冊(cè)的協(xié)議,如果有,則調(diào)用相應(yīng)的處理函數(shù),然后再到ptype_base中,找到合適的協(xié)議,將skb發(fā)送到相關(guān)協(xié)議的處理函數(shù).比如ip協(xié)議(ip_rcv)或者arp(arp_rcv)等等.此篇筆記講的是有關(guān)ptype_all和ptype_base的相關(guān)知識(shí)點(diǎn).

ptype_base和ptype_all在內(nèi)核中存儲(chǔ)的情況如下圖:



可以看到,ptype_base為一個(gè)hash表,而ptype_all為一個(gè)雙向鏈表.每一個(gè)里面注冊(cè)的協(xié)議都用一個(gè)struct packet_type表示.

struct packet_type
{
unsigned short type; /*協(xié)議類(lèi)型*/
struct net_device *dev;
int (*func) (struct sk_buff *, struct net_device *,
struct packet_type *);
void *data; /* Private to the packet type */
struct packet_type *next;
};
其中需要注意的是dev參數(shù),此參數(shù)表明了協(xié)議只處理來(lái)自dev指向device的數(shù)據(jù),當(dāng)dev=NULL時(shí),表示該協(xié)議處理來(lái)自所有device的數(shù)據(jù).這樣,當(dāng)注冊(cè)自己的協(xié)議時(shí),就可以指定自己想要監(jiān)聽(tīng)或者接收的device.
其中注冊(cè)和注銷(xiāo)協(xié)議的函數(shù)為:
dev_add_pack(...)和dev_remove_pack(...)
這兩個(gè)函數(shù)很簡(jiǎn)單,分別如下:
void dev_add_pack(struct packet_type *pt)
{
int hash;
br_write_lock_bh(BR_NETPROTO_LOCK);
#ifdef CONFIG_NET_FASTROUTE
/* Hack to detect packet socket */
if ((pt->data) && ((int)(pt->data)!=1)) {
netdev_fastroute_obstacles++;
dev_clear_fastroute(pt->dev);
}
#endif
if (pt->type == htons(ETH_P_ALL)) {
netdev_nit++;
pt->next=ptype_all;
ptype_all=pt;
} else {
hash=ntohs(pt->type)&15;
pt->next = ptype_base[hash];
ptype_base[hash] = pt;
}
br_write_unlock_bh(BR_NETPROTO_LOCK);
}
此函數(shù)判斷協(xié)議類(lèi)型,然后加到ptype_base或者ptype_all中.
void dev_remove_pack(struct packet_type *pt)
{
struct packet_type **pt1;
br_write_lock_bh(BR_NETPROTO_LOCK);
if (pt->type == htons(ETH_P_ALL)) {
netdev_nit--;
pt1=&ptype_all;
} else {
pt1=&ptype_base[ntohs(pt->type)&15];
}
for (; (*pt1) != NULL; pt1 = &((*pt1)->next)) {
if (pt == (*pt1)) {
*pt1 = pt->next;
#ifdef CONFIG_NET_FASTROUTE
if (pt->data)
netdev_fastroute_obstacles--;
#endif
br_write_unlock_bh(BR_NETPROTO_LOCK);
return;
}
}
br_write_unlock_bh(BR_NETPROTO_LOCK);
printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);
}
此函數(shù)也很簡(jiǎn)單,只是把協(xié)議從相關(guān)的鏈表中移除.
下面以ip協(xié)議為例子來(lái)看看相關(guān)的實(shí)現(xiàn):
ip協(xié)議結(jié)構(gòu)體的定義如下:
static struct packet_type ip_packet_type =
{
__constant_htons(ETH_P_IP),
NULL, /* All devices */
ip_rcv,
(void*)1,
NULL,
};
當(dāng)ipv4協(xié)議棧初始化時(shí),會(huì)調(diào)用ip_init.之后,所有協(xié)議類(lèi)型為ETH_P_IP的包都會(huì)交由ip_rcv處理.代碼如下:
void __init ip_init(void)
{
dev_add_pack(&ip_packet_type);
ip_rt_init();
inet_initpeers();
#ifdef CONFIG_IP_MULTICAST
proc_net_create("igmp", 0, ip_mc_procinfo);
#endif
}
這樣在系統(tǒng)啟動(dòng)之后,ip協(xié)議便被注冊(cè)到ptype_base鏈表中,相應(yīng)的處理函數(shù)為ip_rcv.
arp協(xié)議和其他類(lèi)型的協(xié)議(在ptype_base或者ptype_all中的)的執(zhí)行過(guò)程同理.
本人初學(xué)網(wǎng)絡(luò),水平很菜,如有錯(cuò)誤,希望看到的朋友們及時(shí)指出,不勝感激.
ps1:記得剛來(lái)實(shí)驗(yàn)室的時(shí)候,做的截包模塊的第一種方法是用的netfilter,第二種方法主要就是用到的這塊知識(shí).現(xiàn)在總結(jié)起來(lái),覺(jué)得還算簡(jiǎn)單,當(dāng)初卻用了很長(zhǎng)時(shí)間,想想,真是難者不會(huì),會(huì)者不難啊.今天看書(shū)的時(shí)候,好像又發(fā)現(xiàn)了另外一種方法可以實(shí)現(xiàn)我的要求,記錄在ps2上.
ps2:在數(shù)據(jù)鏈路層截包的另一種方法:用PF_PACKET socket type.linux可以用此類(lèi)型套節(jié)字直接從鏈路層截獲或者注入數(shù)據(jù).發(fā)送數(shù)據(jù)時(shí),直接發(fā)送到dev_queue_xmit.而接收函數(shù)時(shí),可以在數(shù)據(jù)包通過(guò)路由之前截獲到.如tcpdump和Ethereal都是用到了此套接字.那么總結(jié)起來(lái)可以看出,截獲數(shù)據(jù)包至少可以有三種方法實(shí)現(xiàn),第一種的netfilter是在協(xié)議棧中截獲數(shù)據(jù)包,而利用ptype_all或者ptype_base和后面這種套節(jié)字的方法是在鏈路層截獲數(shù)據(jù)包.


  1. //當(dāng)網(wǎng)絡(luò)設(shè)備收到網(wǎng)絡(luò)數(shù)據(jù)包時(shí),最終會(huì)在軟件中斷環(huán)境里調(diào)用此函數(shù)
  1. int netif_receive_skb(struct sk_buff *skb)
  2. {
  3. //ptype_all 用于sniffer這樣的程序
  4. // 發(fā)送一份拷貝給這些注冊(cè)的sniffer程序
  5. list_for_each_entry_rcu(ptype, &ptype_all, list) {
  6. if (!ptype->dev || ptype->dev == skb->dev) {
  7. if (pt_prev)
  8. ret = deliver_skb(skb, pt_prev, orig_dev);
  9. pt_prev = ptype;
  10. }
  11. }
  12. // 內(nèi)核編譯開(kāi)Bridge_config,則將該數(shù)據(jù)包讓網(wǎng)橋函數(shù)來(lái)處理,否則handle_bridge定義為空操作,
  13. // 返回skb,讓協(xié)議棧來(lái)處理上層協(xié)議。
  14. skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
  15. if (!skb)
  16. goto out;
  17. skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
  18. if (!skb)
  19. goto out;
  20. //對(duì)該數(shù)據(jù)包轉(zhuǎn)達(dá)到其他L3協(xié)議的處理函數(shù)
  21. type = skb->protocol;
  22. list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
  23. if (ptype->type == type &&
  24. (!ptype->dev || ptype->dev == skb->dev)) {
  25. if (pt_prev)
  26. ret = deliver_skb(skb, pt_prev, orig_dev);
  27. pt_prev = ptype;
  28. }
  29. }
  30. }

netif_receive_skb()的主要作用體現(xiàn)在兩個(gè)遍歷鏈表的操作中,其中之一為遍歷ptype_all 鏈,這些為注冊(cè)到內(nèi)核的一些 sniffer,將上傳給這些sniffer,另一個(gè)就是遍歷 ptype_base,這個(gè)就是具體的協(xié)議類(lèi)型。當(dāng) eth1 接收到一個(gè)IP數(shù)據(jù)包時(shí),它首先分別發(fā)送一份副本給每個(gè) ptype_all 鏈表中的 packet_type,它們都由 package_rcv 處理,然后再根據(jù)HASH 值,在遍歷另一個(gè)HASH 表時(shí),發(fā)送一份給類(lèi)型為 ETH_P_IP 的類(lèi)型,它由 ip_rcv處理。如果這個(gè)鏈中還注冊(cè)有其它 IP層的協(xié)議,它也會(huì)同時(shí)發(fā)送一個(gè)副本給它。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
TCP/IP協(xié)議棧初始化流程
linux網(wǎng)橋內(nèi)核實(shí)現(xiàn)分析(三)---協(xié)議類(lèi)型查找過(guò)程
rcu學(xué)習(xí)心得
理解 TCP/IP 網(wǎng)絡(luò)棧
TCP/IP學(xué)習(xí)(28)
netfilter: Linux 防火墻在內(nèi)核中的實(shí)現(xiàn)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服