程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> WinPcap編程(一),WinPcap編程(

WinPcap編程(一),WinPcap編程(

編輯:關於C語言

WinPcap編程(一),WinPcap編程(


 

0.

按著文檔順序寫的。

開發環境:win10+VS2013。

配置WinPcap環境就不多說。直接給網址:http://blog.sina.com.cn/s/blog_57432f380101qh3n.html

內容大多是函數解釋+碰到的問題的解決方案。學習&&警示。

 

1.獲取適配器列表

  獲取適配器的目的是:獲取本機有哪些適配器,便於之後選擇用哪個適配器抓包。

  首先,先了解一個數據類型pcap_if/pcap_if_t,這是一個鏈表結構,用來存儲本機的所有適配器。

struct pcap_if {  struct pcap_if *next;  char *name;    char *description;   struct pcap_addr *addresses;  bpf_u_int32 flags;  }; typedef struct pcap_if pcap_if_t; View Code

備注:

  第一是一個pcap_if的鏈表指向下一個設備接口;

  第二個是設備的實際的名字,這個名字是機器能識別的名字,供pcap_open_live()調用;

  第三個是設備的文本描述符,這個描述符就是人們能夠識別的文本符號;有可能為null。

  第四個是一個地址指針,指向的是一系列接口(pcap_addr)的第一個指針;

  第五個是一個標志位,目前這個標志位主要是不是loopback設備。

  

  然後,獲取適配器列表的函數是:

int pcap_findalldevs_ex ( char * source ; struct pcap_rmauth * auth; pcap_if_t ** alldevs; char * errbuf; ) View Code

備注:

  1.source可以使用上面設置好的source,也可以使用:PCAP_SRC_FILE_STRING 或者 PCAP_SRC_IF_STRING,分別是文件和接口的字符串。"file://", "rpcap://"。

      2.auth是遠程登錄信息(pcap_rmauth),有用戶名、密碼、類型。用戶名和密碼都是字符指針,類型有:RPCAP_RMTAUTH_NULL 和 RPCAP_RMTAUTH_PWD。多為BULL。

      3.alldevs用於存儲返回的接口信息。我們要事先定義pcap_if_t *alldevs,這是一個鏈表,存儲接口信息。

      4.errbuf出錯信息。

  5.返回值為0則順利;-1代表出現錯誤。

 

  最後,釋放設備函數:

void pcap_freealldevs (pcap_if_t *alldevsp) View Code

  釋放內存。

 

  原裝代碼:

#define WIN32 #include "pcap.h" void main() { pcap_if_t *alldevs, *d; int i = 0; char errbuf[PCAP_ERRBUF_SIZE]; /* PCAP_ERRBUF_SIZE =256在pcap.h中定義*/ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) /* 這個API用來獲得網卡的列表 */ { fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf); //errbuf參數 當有異常情況發生時,這個參數會被PCAP填充為某3個特定的錯誤字串 return; } /* 顯示列表的響應字段的內容*/ for (d = alldevs; d; d = d->next) { printf("%d. %s,%s\n", ++i, d->name,d->addresses); if (d->description) { printf(" (%s)\n", d->description); //system("pause"); } else printf(" (No description available)\n"); } if (i == 0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return; } /*We don't need any more the device list. Free it */ pcap_freealldevs(alldevs); system("pause"); } View Code

   

2.獲取適配器的高級信息。

  每一個pcap_if_t中包含一個pcap_addr。pcap_addr中包含這個設備的高級信息。

  

struct pacap_addr{ struct pcap_addr *next; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; struct sockaddr *dstaddr; /*destination*/ }; View Code

備注: 

  第二個,地址列表;

  第三個,掩碼列表;

  第四個,廣播地址列表;

  第五個,目的地址列表。

 

  然後,1中獲得適配器列表的鏈表結構後,從頭開始遍歷,把pcap_if_t中pcap_addr的信息給輸出出來就OK了。

  

#define WIN32 #include "pcap.h" #ifndef WIN32 #include <winsock.h> #include <wininet.h> #include <ws2def.h> #include<WS2tcpip.h> #else #include <winsock.h> #endif // 函數原型 void ifprint(pcap_if_t *d); char *iptos(u_long in); char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen); int main() { pcap_if_t *alldevs; pcap_if_t *d; char errbuf[PCAP_ERRBUF_SIZE + 1]; char source[PCAP_ERRBUF_SIZE + 1]; printf("Enter the device you want to list:\n" "rpcap:// ==> lists interfaces in the local machine\n" "rpcap://hostname:port ==> lists interfaces in a remote machine\n" " (rpcapd daemon must be up and running\n" " and it must accept 'null' authentication)\n" "file://foldername ==> lists all pcap files in the give folder\n\n" "Enter your choice: "); fgets(source, PCAP_ERRBUF_SIZE, stdin); source[PCAP_ERRBUF_SIZE] = '\0'; /* 獲得接口列表 */ if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1) { fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* 掃描列表並打印每一項 */ for (d = alldevs; d; d = d->next) { ifprint(d); } pcap_freealldevs(alldevs); system("pause"); return 1; } /* 打印所有可用信息 */ void ifprint(pcap_if_t *d) { pcap_addr_t *a; char ip6str[128]; /* 設備名(Name) */ printf("%s\n", d->name); /* 設備描述(Description) */ if (d->description) printf("\tDescription: %s\n", d->description); /* Loopback Address*/ printf("\tLoopback: %s\n", (d->flags & PCAP_IF_LOOPBACK) ? "yes" : "no"); /* IP addresses */ for (a = d->addresses; a; a = a->next) { printf("\tAddress Family: #%d\n", a->addr->sa_family); switch (a->addr->sa_family) { case AF_INET: printf("\tAddress Family Name: AF_INET\n"); if (a->addr) printf("\tAddress: %s\n", iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr)); if (a->netmask) printf("\tNetmask: %s\n", iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr)); if (a->broadaddr) printf("\tBroadcast Address: %s\n", iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr)); if (a->dstaddr) printf("\tDestination Address: %s\n", iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr)); break; case AF_INET6: printf("\tAddress Family Name: AF_INET6\n"); if (a->addr) printf("\tAddress: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str))); break; default: printf("\tAddress Family Name: Unknown\n"); break; } } printf("\n"); } View Code /* 將數字類型的IP地址轉換成字符串類型的 */ #define IPTOSBUFFERS 12 char *iptos(u_long in) { static char output[IPTOSBUFFERS][3 * 4 + 3 + 1]; static short which; u_char *p; p = (u_char *)&in; which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen) { socklen_t sockaddrlen; #ifdef WIN32 sockaddrlen = sizeof(struct sockaddr_in6); #else sockaddrlen = sizeof(struct sockaddr_storage); #endif if (getnameinfo(sockaddr, sockaddrlen, address, addrlen, NULL, 0, NI_NUMERICHOST) != 0) address = NULL; return address; } 輔助函數,IP轉字符串

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved