MyCapView.cpp
上传用户:xakehao
上传日期:2013-08-28
资源大小:100k
文件大小:11k
源码类别:

CA认证

开发平台:

Visual C++

  1. // MyCapView.cpp : implementation of the CMyCapView class
  2. #include "stdafx.h"
  3. #include "MyCap.h"
  4. #include "MyCapDoc.h"
  5. #include "MyCapView.h"
  6. #include <pcap.h>
  7. #include "InterfaceDlg.h"
  8. #include <vector>
  9. #include "packetfilter.h"
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. using namespace std;
  16. typedef vector<const u_char *> v;
  17. v myvector;//定义了一个vector变量,用来放抓的包
  18. using namespace std;
  19. typedef vector<u_short> u;
  20. u mycount;//定义了一个vector变量,用来放所抓包的大小
  21. using namespace std;
  22. typedef vector<PACKET> c;
  23. c mypacket;//定义了一个vector变量,用来放所抓包的包头
  24. char *packet_filter = "";
  25. int m_flag = -1;
  26. HWND hWnd;
  27. #define WM_USER_THREAD_PACKET WM_USER+100
  28. IMPLEMENT_DYNCREATE(CMyCapView, CListView)
  29. BEGIN_MESSAGE_MAP(CMyCapView, CListView)
  30. ON_COMMAND(ID_FILE_START, OnFileStart)
  31. ON_COMMAND(ID_OPTION_CARD, OnOptionCard)
  32. ON_COMMAND(ID_FILE_STOP, OnFileStop)
  33. ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
  34. ON_COMMAND(ID_FILE_SAVE, OnFileSave)
  35. ON_COMMAND(ID_OPTION_FILTER, OnOptionFilter)
  36. ON_COMMAND(ID_FILE_PRINT, CListView::OnFilePrint)
  37. ON_COMMAND(ID_FILE_PRINT_DIRECT, CListView::OnFilePrint)
  38. ON_COMMAND(ID_FILE_PRINT_PREVIEW, CListView::OnFilePrintPreview)
  39.   ON_MESSAGE(WM_USER_THREAD_PACKET, OnGetPacket)
  40. END_MESSAGE_MAP()
  41. CMyCapView::CMyCapView()
  42. {
  43.   strcpy(m_szName, "");//将m_szName初始化为空
  44. }
  45. CMyCapView::~CMyCapView()
  46. {
  47. }
  48. BOOL CMyCapView::PreCreateWindow(CREATESTRUCT& cs)
  49. {
  50.   cs.style |= LVS_REPORT; 
  51. return CListView::PreCreateWindow(cs);
  52. }
  53. void CMyCapView::OnDraw(CDC* pDC)
  54. {
  55. CMyCapDoc* pDoc = GetDocument();
  56. ASSERT_VALID(pDoc);
  57. }
  58. void CMyCapView::OnInitialUpdate()
  59. {
  60. CListView::OnInitialUpdate();
  61.   CListCtrl& theCtrl = GetListCtrl();
  62.   theCtrl.SetExtendedStyle(theCtrl.GetExtendedStyle()|LVS_EX_FULLROWSELECT );  
  63.   theCtrl.InsertColumn(0, _T("时间"), LVCFMT_CENTER, 100);//给第一个CListView窗口添加各列
  64.   theCtrl.InsertColumn(1, _T("长度"), LVCFMT_CENTER, 100);
  65.   theCtrl.InsertColumn(2, _T("源IP"), LVCFMT_CENTER, 100);
  66.   theCtrl.InsertColumn(3, _T("目的IP"), LVCFMT_CENTER, 100);
  67.   theCtrl.InsertColumn(4, _T("源端口"), LVCFMT_CENTER, 100);
  68.   theCtrl.InsertColumn(5, _T("目的端口"), LVCFMT_CENTER, 100); 
  69.   CString strSection       = "global";
  70.   CString strStringItem1    = "interface";
  71.   CString strStringItem2    = "description";
  72.   CString strStringItem3    = "netmask";
  73.   CWinApp *pApp = AfxGetApp();
  74.   strcpy(m_szName, pApp->GetProfileString(strSection, strStringItem1).GetBuffer(255));
  75.   strcpy(m_szDescription, pApp->GetProfileString(strSection, strStringItem2).GetBuffer(255));
  76.   strcpy(m_szNetmask, pApp->GetProfileString(strSection, strStringItem3).GetBuffer(16));
  77. }
  78. BOOL CMyCapView::OnPreparePrinting(CPrintInfo* pInfo)
  79. {
  80. return DoPreparePrinting(pInfo);
  81. }
  82. void CMyCapView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  83. {
  84. }
  85. void CMyCapView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  86. {
  87. }
  88. #ifdef _DEBUG
  89. void CMyCapView::AssertValid() const
  90. {
  91. CListView::AssertValid();
  92. }
  93. void CMyCapView::Dump(CDumpContext& dc) const
  94. {
  95. CListView::Dump(dc);
  96. }
  97. CMyCapDoc* CMyCapView::GetDocument() 
  98. {
  99. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyCapDoc)));
  100. return (CMyCapDoc*)m_pDocument;
  101. }
  102. #endif //_DEBUG
  103. void CMyCapView::OnFileStart() 
  104. {
  105.   CString strMsg;
  106.   hWnd = GetSafeHwnd( ) ;
  107.   if (strlen(m_szName) == 0 || strlen(m_szNetmask) == 0)
  108.   {
  109.     OnOptionCard(); //如果没有选择网卡就要求选择网卡 
  110.   }
  111.   else
  112.   {
  113.     THREADPARMS *ptp = new THREADPARMS;    
  114.     strcpy(ptp->szName, m_szName);
  115.     ptp->netmask = atoi(m_szNetmask);    
  116.     pThread = AfxBeginThread(ThreadFunc, ptp);
  117.   char szStatus[255] = "";
  118.     sprintf(szStatus,"listening on %s...", m_szDescription);
  119.   CStatusBar* pStatus = (CStatusBar*)(AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR));
  120.     pStatus->SetPaneText(0, szStatus, TRUE);
  121.   }  //打开网卡,如果成功,就开始抓包
  122. }
  123. void CMyCapView::OnFileStop() 
  124. {
  125.   ::TerminateThread(pThread->m_hThread, 0);//终止线程  
  126.   char szStatus[255] = "";
  127.   sprintf(szStatus,"stop");
  128. CStatusBar* pStatus = (CStatusBar*)(AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR));
  129.   pStatus->SetPaneText(0, szStatus, TRUE);
  130. }
  131. LONG CMyCapView::OnGetPacket(WPARAM wParam, LPARAM lParam)
  132. {
  133.   PACKET pkt;
  134.   memcpy(&pkt, (PACKET *)wParam, sizeof(PACKET));
  135.   delete (PACKET *)wParam;
  136.   mypacket.push_back(pkt);//将包头放到一个向量mypacket中
  137.   CListCtrl& theCtrl = GetListCtrl();
  138.   int nCount = theCtrl.GetItemCount();
  139.   char srcIP[16] = "";
  140.   char dstIP[16] = "";
  141.   char srcPort[8] = "";
  142.   char dstPort[8] = "";
  143.   char szLen[8] = "";
  144.   sprintf(srcIP, "%d.%d.%d.%d", 
  145.     pkt.IpHead.saddr.byte1,
  146.     pkt.IpHead.saddr.byte2,
  147.     pkt.IpHead.saddr.byte3,
  148.     pkt.IpHead.saddr.byte4);
  149.   sprintf(dstIP, "%d.%d.%d.%d", 
  150.     pkt.IpHead.daddr.byte1,
  151.     pkt.IpHead.daddr.byte2,
  152.     pkt.IpHead.daddr.byte3,
  153.     pkt.IpHead.daddr.byte4);
  154.   sprintf(szLen, "%d", ntohs(pkt.IpHead.tlen));
  155. if(int(pkt.IpHead.proto) == 17)
  156. {//如果IP包头的协议字段是17,即为UDP包时,在第一个CListView窗口中显示UDP包信息
  157. sprintf(srcPort, "%d", ntohs(pkt.UdpHead.sport));
  158. sprintf(dstPort, "%d", ntohs(pkt.UdpHead.dport));
  159. theCtrl.InsertItem(nCount, pkt.timestr, NULL);
  160. theCtrl.SetItemText(nCount, 1, szLen);
  161. theCtrl.SetItemText(nCount, 2, srcIP);
  162. theCtrl.SetItemText(nCount, 3, dstIP);
  163. theCtrl.SetItemText(nCount, 4, srcPort);
  164. theCtrl.SetItemText(nCount, 5, dstPort);
  165. }
  166. if(int(pkt.IpHead.proto == 6))
  167. {//如果IP包头的协议字段是6,即为TCP包时,在第一个CListView窗口中显示TCP包信息
  168. sprintf(srcPort, "%d", ntohs(pkt.TcpHead.tcpsport));
  169. sprintf(dstPort, "%d", ntohs(pkt.TcpHead.tcpdport));
  170. theCtrl.InsertItem(nCount, pkt.timestr, NULL);
  171. theCtrl.SetItemText(nCount, 1, szLen);
  172. theCtrl.SetItemText(nCount, 2, srcIP);
  173. theCtrl.SetItemText(nCount, 3, dstIP);
  174. theCtrl.SetItemText(nCount, 4, srcPort);
  175. theCtrl.SetItemText(nCount, 5, dstPort);
  176. }
  177. if(int(pkt.IpHead.proto == 1))
  178. {//如果IP包头的协议字段是1,即为ICMP包时,在第一个CListView窗口中显示ICMP包信息
  179. theCtrl.InsertItem(nCount, pkt.timestr, NULL);
  180. theCtrl.SetItemText(nCount, 1, szLen);
  181. theCtrl.SetItemText(nCount, 2, srcIP);
  182. theCtrl.SetItemText(nCount, 3, dstIP);
  183. }
  184.  
  185.   return 0;
  186. void CMyCapView::OnOptionCard() 
  187. {
  188.   CString strSection       = "global";
  189.   CString strStringItem1    = "interface";
  190.   CString strStringItem2    = "description";
  191.   CString strStringItem3    = "netmask";
  192.   CInterfaceDlg dlg;
  193.   if (dlg.DoModal() == IDOK)
  194.   {
  195.     strcpy(m_szName, dlg.m_szName);
  196.     strcpy(m_szDescription, dlg.m_szDescription);
  197.     strcpy(m_szNetmask, dlg.m_szNetmask);
  198.     CWinApp *pApp = AfxGetApp();
  199.     pApp->WriteProfileString(strSection, strStringItem1, dlg.m_szName);
  200.     pApp->WriteProfileString(strSection, strStringItem2, dlg.m_szDescription);
  201.     pApp->WriteProfileString(strSection, strStringItem3, dlg.m_szNetmask);
  202.   }
  203.   else
  204.   {
  205.     MessageBox("请确保正确安装了winpcap!");
  206.     return;
  207.   }
  208. }
  209. UINT ThreadFunc(LPVOID pParam)
  210. {
  211.   THREADPARMS *ptp = (THREADPARMS *) pParam;
  212.   char szName[255];
  213.   strcpy(szName, ptp->szName);
  214.   u_int netmask = ptp->netmask;
  215.   CString strMsg;
  216.   delete ptp;  
  217.   pcap_t *adhandle;
  218.   char errbuf[PCAP_ERRBUF_SIZE];  
  219.   if(packet_filter == "")  
  220.   packet_filter = "ip";
  221.   struct bpf_program fcode;
  222. if ( (adhandle= pcap_open(szName,
  223.  65536,
  224.  PCAP_OPENFLAG_PROMISCUOUS,
  225.  1000,
  226.  NULL,
  227.  errbuf
  228.  ) ) == NULL)//将网卡设置成混杂模式
  229. {
  230. strMsg.Format("Unable to open the adapter. %s is not supported by WinPcapn", szName);
  231.     AfxMessageBox(strMsg);
  232. return 0;
  233. }
  234.   if(pcap_datalink(adhandle) != DLT_EN10MB)
  235. {
  236.     AfxMessageBox("This program works only on Ethernet networks.");
  237. return 0;
  238. }
  239. if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )
  240. {
  241. AfxMessageBox("Unable to compile the packet filter. Check the syntax.");
  242. return 0;
  243. }
  244. if (pcap_setfilter(adhandle, &fcode)<0)//设置过滤器
  245. {
  246. AfxMessageBox("Error setting the filter.");
  247. return 0;
  248. }
  249. pcap_loop(adhandle, 0, packet_handler, NULL);
  250.   return 0;    
  251. }
  252. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
  253. {
  254. struct tm *ltime;
  255. char timestr[16];
  256. ip_header *ih;
  257. udp_header *uh;
  258. tcp_header *th;
  259. icmp_header *ich;
  260. u_int ip_len;
  261. u_short totallen;
  262. myvector.push_back(pkt_data);//把收到的包放到一个向量myvector里面
  263. ltime=localtime(&header->ts.tv_sec);
  264. strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
  265. ih = (ip_header *) (pkt_data +14); //从包中解开IP头并将其赋给ih
  266. ip_len = (ih->ver_ihl & 0xf) * 4;
  267. totallen = ntohs(ih->tlen);
  268. totallen += 18;
  269. mycount.push_back(totallen);//将整个包的大小值放到一个向量mycount里面
  270.   PACKET *pkt = new PACKET;
  271.   strcpy(pkt->timestr, timestr);  
  272.   memcpy(&(pkt->IpHead), ih, sizeof(ip_header));
  273.   if(int(ih->proto) == 17)
  274. {//如果是UDP包就从解开UDP头并将其赋给uh
  275.   uh = (udp_header *) ((u_char*)ih + ip_len);
  276.   memcpy(&(pkt->UdpHead), uh, sizeof(udp_header));
  277. }
  278.   if(int(ih->proto) == 6)
  279.   {//如果是TCP包就从解开TCP头并将其赋给th
  280.   th = (tcp_header *)((u_char*)ih + ip_len);   
  281.   memcpy(&(pkt->TcpHead), th, sizeof(tcp_header));
  282.   }
  283.   if(int(ih->proto) == 1)
  284.   {//如果是ICMP包就从解开ICMP头并将其赋给ich
  285.   ich = (icmp_header *)((u_char*)ih + ip_len);
  286.   memcpy(&(pkt->IcmpHead), ich, sizeof(icmp_header));
  287.   }  
  288.   ::PostMessage(hWnd, WM_USER_THREAD_PACKET, (WPARAM) (pkt), 0);
  289. }
  290. void CMyCapView::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
  291. {//如果选中CListView窗口中的某项,将这项的索引号赋给m_index
  292. CMyCapDoc* pDoc = GetDocument();
  293. DWORD dwPos = ::GetMessagePos();
  294. CPoint point((int) LOWORD(dwPos), (int) HIWORD(dwPos));
  295. GetListCtrl().ScreenToClient(&point);
  296. int m_index;
  297. if((m_index = GetListCtrl().HitTest(point)) !=-1)
  298. m_flag = m_index;
  299. pDoc->SetCount(m_index);
  300. *pResult = 0;
  301. }
  302. void CMyCapView::OnFileSave() 
  303. {
  304. int num = 0;
  305. UINT count = 0;
  306. count = myvector.size();
  307. CFileDialog dlg(FALSE, "txt", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "*.txt");
  308. //实例化一个CFileDialog类对象
  309. if(dlg.DoModal() == IDOK)
  310. {
  311. CFile myfile;
  312. CString name = dlg.GetFileName();
  313. myfile.Open(name, CFile::modeCreate | CFile::modeReadWrite);//打开文件
  314. for (int i = 0; i < count; i++)
  315. {
  316. num = mycount[i];
  317. myfile.Write(myvector[i], num);//将包的内容写入文件
  318. }
  319. myfile.Close();
  320. }
  321. }
  322. void CMyCapView::OnOptionFilter() 
  323. {
  324. packetfilter filterDlg;
  325. filterDlg.DoModal();
  326. if(filterDlg.m_tcp == FALSE && filterDlg.m_udp == TRUE)
  327. packet_filter = "ip and udp";//如果选择抓UDP包,将过滤器字段设置成“ip and udp”,即抓UDP包
  328. if(filterDlg.m_tcp == TRUE && filterDlg.m_udp == FALSE)
  329. packet_filter = "ip and tcp";
  330. if(filterDlg.m_tcp == TRUE && filterDlg.m_udp == TRUE)
  331. packet_filter = "ip";
  332. if(filterDlg.m_icmp == TRUE)
  333. packet_filter = "icmp";
  334. }