• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 一個險惡bug的深入分析(3)

    發表于:2012-06-06來源:伯樂在線作者:不詳點擊數: 標簽:bug
    這段代碼對存儲了所有pcap條目信息的列表ptype_all進行遍歷, 判斷pcap條目的設備結構能否匹配skb所屬設備。 循環中對設備的檢查非常有意思: 1 if (!ptype-d

      這段代碼對存儲了所有pcap條目信息的列表ptype_all進行遍歷, 判斷pcap條目的設備結構能否匹配skb所屬設備。

      循環中對設備的檢查非常有意思:

    1
    if (!ptype->dev || ptype->dev == skb->dev)

      如果你試圖嗅探來自eth0的數據包,但是由于eth0已經是bond的一部分,因而這個檢查一定會失敗。原因是skb->dev已經被重寫為bond設備的dev結構了。

      這就是為什么tcpdump和其他的測量工具嗅探bond相關的物理設備時看不到發送的數據包了!

      只要簡單地把if語句修改成:

    1
    if (!ptype->dev || ptype->dev == skb->dev || ptype->dev == orig_dev) {

      因為加入了orig_dev檢查,這下pcap就能夠處理被dev指針被修改過的skb了。

      讓我們來測試一下這個修改。

      有意思的現象,第二輪觀察

      接下來,重新構建并安裝修改后的內核(順便說一下,這里有一份非常有用的文檔),重新ping目標機器并開始嗅探發向物理設備的數據包:

    1
    2
    3
    4
    5
    % sudo tcpdump -i eth0 dst 172.16.209.136 and proto 1
    ^C
    0 packets captured
    2 packets received by filter
    0 packets dropped by kernel

      什么情況?

      為什么修改以后還是沒有看到發送的數據包?

      libpcap

      讓我們快速檢查一下內核中負責處理AF_PACKET地址家族的libpcap接口。

      AF_PACKET 在內核中是單獨實現的一個地址家族,相關的代碼位于net/packet/af_packet.c。libpcap通過調用socket系統調用建立一個socket,調用的第一個參數被設置為PACKET。libpcap接下來會使用bind系統調用把這個socket綁定想要嗅探的設備上。

      現在有兩種方法可以從內核中拿到數據包:

      • “以前的方法”: 對每個數據包的文件描述符調用recvfrom函數。在老版本的內核上,只有這一個函數可用。

      • “新方法”:調用poll函數會通知libpcap有一組數據包到達,在內核與libpcap的共享內存中等待讀取。比起“老辦法”這種方法效率更高(使用的系統調用更少),在最近大多數的內核包括Debian Lenny都支持這種辦法。

      結果是,盡管Debian Lenny的內核支持“新方法”實現的AF_PACKET,但是相應的libpcap卻不支持。這就意味著tcpdump(依賴于libpcap)只能逐次逐個地從內核中取得數據包。

      更新版本的libpcap默認使用“新方法”從內核讀取數據包。因為Lenny支持這種用法,我試著構建了一個更新版本的libpcap并修改了tcpdump。在修改過的Lenny內核上測試這個修改,我看到當我在bond上的物理設備進行嗅探時,數據包從RX路徑流出。如果我把新的libpcap修改成使用“以前的方法”搜集數據包,沒有數據包從RX路徑流出。

      這意味著在使用“以前的方法”時,要么AF_PACKET有bug,要么多版本的libpcap有bug。

      if語句

      經過數小時痛苦地閱讀代碼,我找了一條if語句可以控制libpcap使用“以前的方法”讀取數據包。

    1
    2
    3
    4
    5
    // From pcap_read_packet in pcap-linux.c:
     
    if (handle->md.ifindex != -1 &&
        from.sll_ifindex != handle->md.ifindex)
      return 0;

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>