Winpcap學習筆記(2)

來源:互聯網
上載者:User

著作權資訊:

本文來自internet,轉載這裡供網路編程愛好者學習和研究使用,請尊重作者的勞動成果。未經授權而在商業上使用原作者的文章屬侵權行為,後果由使用者自負,本人不承擔任何法律責任。

 

今天在閱讀Winpcap Manual的時候發現一句話:

       “This means that on shared media (like non-switched Ethernet), WinPcap will be able to capture the packets of other hosts.”

   我理解為:如果在通過沒有交換功能的集線器串連的網路上,只要把網卡設定為混雜(promiscuous)模式,winpcap能夠捕獲到其他主機通訊的資料包。如果是具有交換功能的集線器串連的網路winpcap還能管用嗎?這個在後邊的實習中將會進行實驗。

    實驗程式2:

/*
* 截獲資料包的實驗。先列印出所有網路介面卡的列表,然後選擇
* 想在哪個適配器上截獲資料包。然後通過pcap_loop()函數將截獲
* 的資料包傳給回呼函數packet_handler()處理。

* 通過該程式初步瞭解了使用winpcap截獲資料包的步驟以及一些在
* 截獲資料包時非常重要的函數和結構體。
* 2006-1-26
*/

#include <pcap.h>
#include <remote-ext.h>

/* Prototype of the packet handler */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

int main() {
 pcap_if_t *alldevs;
 pcap_if_t *d;
 int inum;
 int i = 0;
 pcap_t *adhandle;
 char errbuf[PCAP_ERRBUF_SIZE];

 /* Retrieve the devices list on the local machine */
 if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
 {
  fprintf(stderr, "Error in pcap_findalldevs: %s/n", errbuf);
  exit(1);
 }

 /* Print the list */
 for (d = alldevs; d; d = d->next)
 {
  /* Print name */
  printf("%d. %s", ++ i, d->name);

  /* Print description */
  if (d->description)
  {
   printf(" (%s)/n", d->description);
  }
  else
  {
   printf(" (No description available)/n");
  }
 }

 if (i == 0)
 {
  printf("/nNo interfaces found! Make sure Winpcap is installed./n");
  return -1;
 }

 /* Select an adapter */
 printf("Enter the interface number (1 - %d):", i);
 scanf("%d", &inum);

 if (inum < 1 || inum > i)
 {
  printf("/nInterface number out of range./n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
 }

 /* Jump to the selected adapter */
 for (d = alldevs, i = 0; i < inum - 1; d = d->next, ++ i);

 /*Open the device */
 if ((adhandle = pcap_open(d->name, /* name of the device */
  65536,         /* portion of the packet to capture */
  /* 65535 guarantees that the whole packet will be captured on all the link layers */
  PCAP_OPENFLAG_PROMISCUOUS,     /* promiscuous mode */
  1000,         /* read timeout */
  NULL,         /* authentication on the remote machine */
  errbuf         /* error buffer */
  )) == NULL)
 {
   fprintf(stderr, "/nnable to open the adapter. %s is not supported by Winpcap/n", d->name);
   /* Free the devices list */
   pcap_freealldevs(alldevs);

   return -1;
 }

 printf("/nlistening on %s.../n", d->description);

 /* At this point, we don’t need any more the device list. Free it */
 pcap_freealldevs(alldevs);
 /* start the capture */
 pcap_loop(adhandle, 0, packet_handler, NULL);

 return 1;
}

/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) {
 struct tm *ltime;
 char timestr[16];

 /* convert the timestamp to readable format */
 ltime = localtime(&header->ts.tv_sec);
 strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
 printf("%s, %.6d len:%d/n", timestr, header->ts.tv_usec, header->len);
}

 

函數1:

pcap_t *pcap_open(const char *               source,

int                              snaplen,

int                              flags, [Page]

int                              read_timeout,

struct pcap_rmtauth *       auth,

char *                        errbuf

)

    為捕獲/發送資料開啟一個普通的源。pcap_open()能夠替代所有的pcap_open_xxx()函數,它隱藏了不同的pcap_open_xxx()之間的差異,所以程式員不必使用不同的open函數。

source:的是包含要開啟的源名稱的以’/0’結尾的字串。源名稱得包含新的源規範文法(Source Specification Syntax),並且它不能為NULL。為了方便的使用源文法,請記住:(1)pcap_findalldevs_ex()返回的適配器(網卡)可以直接被pcap_open()使用;(2)萬一使用者想傳遞他自己的源字串給pcap_open(),pcap_createsrcstr()可以建立正確的源標識。

snaplen:需要保留的資料包的長度。對每一個過濾器接收到的資料包,第一個‘snaplen’位元組的內容將被儲存到緩衝區,並且傳遞給使用者程式。例如,snaplen等於100,那麼僅僅每一個資料包的第一個100位元組的內容被儲存。簡言之就是從每一個包的開頭到snaplen的那段內容將被儲存。

flags:儲存一些由於抓包需要的標誌。Winpcap定義了三種標誌:

l         PCAP_OPENFLAG_PROMISCUOUS:1,它定義了適配器(網卡)是否進入混雜模式(promiscuous mode)。

l         PCAP_OPENFLAG_DATATX_UDP:2,它定義了資料轉送(假如是遠程抓包)是否用UDP協議來處理。

l         PCAP_OPENFLAG_NOCAPTURE_RPCAP:4,它定義了遠程探測器是否捕獲它自己產生的資料包。

read_timeout:以毫秒為單位。read timeout被用來設定在遇到一個資料包的時候讀操作不必立即返回,而是等待一段時間,讓更多的資料包到來後從OS核心一次讀多個資料包。並非所有的平台都支援read timeout;在不支援read timeout的平台上它將被忽略。

auth:一個指向’struct pcap_rmtauth’的指標,儲存當一個使用者登入到某個遠程機器上時的必要資訊。假如不是遠程抓包,該指標被設定為NULL。

errbuf:一個指向使用者申請的緩衝區的指標,存放當該函數出錯時的錯誤資訊。

傳回值是一個’pcap_t’指標,它可以作為下一步調用(例如pcap_compile()等)的參數,並且指定了一個已經開啟的Winpcap會話。在遇到問題的情況下,它返回NULL並且’errbuf’變數儲存了錯誤資訊。

 

函數2:

int pcap_loop(  pcap_t*           p,

int                   cnt,

pcap_hander    callback,

u_char*           user

)

    收集一群資料包。pcap_loop()與pcap_dispatch()類似,但是它會一直保持讀資料包的操作直到cnt包被處理或者發生了錯誤。當有活動的讀逾時(read timeout)時它並不返回。然而,對pcap_open_live()指定一個非0的讀逾時(read timeout),當發生逾時的時候調用pcap_dispatch()來接收並處理到來的所有資料包更好。Cnt指明了返回之前要處理資料包的最大數目。如果cnt為負值,pcap_loop()將一直迴圈(直到發生錯誤才停止)。如果出錯時返回-1;如果cnt用完時返回0;如果在任何包被處理前調用pcap_breakloop()來中止迴圈將返回-2。所以,如果程式中使用了pcap_breakloop(),必須準確的來判斷傳回值是-1還是-2,而不能簡單的判斷<0。

 

函數3:

hypedef void (* pcap_handler)(u_char* user,

const struct pcap_pkthdr* pkt_header,

const u_char* pkt_data)

    接收資料包的回呼函數原型。當使用者程式使用pcap_dispatch()或者pcap_loop(),資料包以這種回調的方法傳給應用程式。使用者參數是使用者自己定義的包含捕獲工作階段狀態的參數,它必須跟pcap_dispatch()和pcap_loop()的參數相一致。pkt_hader是與抓包驅動有關的頭。pkt_data指向包裡的資料,包括協議頭。

 

結構體1:

struct pcap_pkthdr {

      struct timeval ts;

      bpf_u_int32 caplen;

      bpf_u_int32 len;

}

ts:時間戳記

cpalen:當前分組的長度

len:資料包的長度
 

本篇文章來源於 中國協議分析網|www.cnpaf.net 原文連結:http://www.cnpaf.net/Class/winpcap/200610/16293.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.