基于MFC和winpcap的简单路由器实现

关键部分代码如下。

[cpp]  view plain  copy
  1. // VCRouterDlg.cpp : 实现文件  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "VCRouter.h"  
  6. #include "VCRouterDlg.h"  
  7. #include "afxdialogex.h"  
  8. #include "pcap.h"    
  9. #include <stdlib.h>    
  10. #include <string.h>    
  11.   
  12.   
  13. #ifdef _DEBUG  
  14. #define new DEBUG_NEW  
  15. #endif  
  16.   
  17. #define           MAX_IF          5          //  最大接口数目    
  18. #pragma pack(1)    
  19.   
  20. typedef struct FrameHeader_t    {      //  帧首部    
  21.   
  22.     UCHAR  DesMAC[6];                       //     目的地址    
  23.   
  24.     UCHAR  SrcMAC[6];                               //  源地址    
  25.   
  26.     USHORT FrameType;                               //  帧类型    
  27.   
  28. } FrameHeader_t;  
  29.   
  30.   
  31.   
  32. typedef struct ARPFrame_t {                   // ARP 帧    
  33.   
  34.     FrameHeader_t           FrameHeader;    //  帧首部    
  35.   
  36.     WORD                  HardwareType; //  硬件类型    
  37.   
  38.     WORD                    ProtocolType; //  协议类型    
  39.   
  40.     BYTE                    HLen;                  //  硬件地址长度    
  41.   
  42.     BYTE                    PLen;                  //  协议地址长度    
  43.   
  44.     WORD                    Operation;        //  操作值    
  45.   
  46.     UCHAR                   SendHa[6];        //  源MAC 地址    
  47.   
  48.     ULONG                   SendIP;              //  源IP 地址    
  49.   
  50.     UCHAR                   RecvHa[6];        //    目的MAC 地址    
  51.   
  52.     ULONG                   RecvIP;              //  目的IP 地址    
  53.   
  54. } ARPFrame_t;  
  55.   
  56.   
  57.   
  58. typedef struct IPHeader_t {                   // IP 首部    
  59.   
  60.     BYTE        Ver_HLen;                          //  版本+头部长度    
  61.   
  62.     BYTE        TOS;                                    //  服务类型    
  63.   
  64.     WORD        TotalLen;                          //  总长度    
  65.   
  66.     WORD        ID;                                      //  标识    
  67.   
  68.     WORD        Flag_Segment;                  //  标志+片偏移    
  69.   
  70.     BYTE        TTL;                                    //  生存时间    
  71.   
  72.     BYTE        Protocol;                          //  协议    
  73.   
  74.     WORD        Checksum;                          //  头部校验和    
  75.   
  76.     ULONG  SrcIP;                                //  源IP 地址    
  77.   
  78.     ULONG  DstIP;                                //  目的IP 地址    
  79.   
  80. } IPHeader_t;  
  81.   
  82.   
  83.   
  84. typedef struct ICMPHeader_t {          // ICMP 首部    
  85.   
  86.     BYTE        Type;                                  //  类型    
  87.   
  88.     BYTE        Code;                                  //  代码    
  89.   
  90.     WORD        Checksum;                          //  校验和    
  91.   
  92.     WORD        Id;                                      //  标识    
  93.   
  94.     WORD        Sequence;                          //  序列号    
  95.   
  96. } ICMPHeader_t;  
  97.   
  98.   
  99.   
  100. typedef struct IPFrame_t {                         // IP 帧    
  101.   
  102.     FrameHeader_t             FrameHeader;    //  帧首部    
  103.   
  104.     IPHeader_t                IPHeader;          // IP 首部    
  105.   
  106. } IPFrame_t;  
  107.   
  108.   
  109.   
  110. typedef struct ip_t {                          //  网络地址    
  111.   
  112.     ULONG                     IPAddr;              // IP 地址    
  113.   
  114.     ULONG                     IPMask;              //  子网掩码    
  115.   
  116. } ip_t;  
  117.   
  118.   
  119.   
  120. typedef struct    IfInfo_t {                       //  接口信息    
  121.   
  122.     CString                   DeviceName;      //  设备名    
  123.   
  124.     CString                   Description;    //  设备描述    
  125.   
  126.     UCHAR                     MACAddr[6];      // MAC 地址    
  127.   
  128.     CArray <ip_t, ip_t&>             ip;              // IP 地址列表    
  129.   
  130.     pcap_t                     *adhandle;        // pcap 句柄    
  131.   
  132. } IfInfo_t;  
  133.   
  134.   
  135.   
  136. typedef struct SendPacket_t {     //  发送数据包结构    
  137.   
  138.     int                       len;                    //  长度    
  139.   
  140.     BYTE                      PktData[2000];//  数据缓存    
  141.   
  142.     ULONG                     TargetIP;          //   目的IP 地址    
  143.   
  144.     UINT_PTR                  n_mTimer;          //  定时器    
  145.   
  146.     UINT                      IfNo;                  //  接口序号    
  147.   
  148. } SendPacket_t;  
  149.   
  150.   
  151.   
  152. typedef struct RouteTable_t {     //  路由表结构    
  153.   
  154.     ULONG  Mask;                                  //  子网掩码    
  155.   
  156.     ULONG  DstIP;                                //    目的地址    
  157.   
  158.     ULONG  NextHop;                            //  下一跳步    
  159.   
  160.     UINT         IfNo;                                  //  接口序号    
  161.   
  162.   
  163. } RouteTable_t;  
  164.   
  165.   
  166.   
  167. typedef struct IP_MAC_t {                  // IP-MAC 地址映射结构    
  168.   
  169.     ULONG  IPAddr;                              // IP 地址    
  170.   
  171.     UCHAR  MACAddr[6];                      // MAC 地址    
  172.   
  173. } IP_MAC_t;  
  174.   
  175.   
  176.   
  177.   
  178.   
  179. //  全局变量    
  180.   
  181. /****************************************************************** 
  182.  
  183. *******/  
  184.   
  185.   
  186.   
  187. IfInfo_t     IfInfo[MAX_IF];                       //  接口信息数组    
  188.   
  189. int                 IfCount;                            //  接口个数    
  190.   
  191. UINT_PTR        TimerCount;                      //  定时器个数    
  192.   
  193.   
  194.   
  195. CList <SendPacket_t, SendPacket_t&> SP;                      //  发送数据包缓存队列    
  196.   
  197. CList  <IP_MAC_t, IP_MAC_t&>  IP_MAC;                              //  IP-MAC 地址映射列表  
  198.   
  199. CList <RouteTable_t, RouteTable_t&> RouteTable;      //  路由表    
  200.   
  201.   
  202.   
  203. //CMyRouterDlg *pDlg;                          //  对话框指针    
  204.   
  205. CVCRouterDlg *pDlg;  
  206.   
  207. CMutex mMutex(0, 0, 0);                          //  互斥    
  208.   
  209.   
  210.   
  211. /****************************************************************** 
  212.  
  213. *******/  
  214.   
  215.   
  216.   
  217. //  全局函数    
  218.   
  219. /****************************************************************** 
  220.  
  221. *******/  
  222.   
  223.   
  224.   
  225. // IP 地址转换    
  226.   
  227. CString IPntoa(ULONG nIPAddr);  
  228.   
  229.   
  230.   
  231. // MAC 地址转换    
  232.   
  233. CString MACntoa(UCHAR *nMACAddr);  
  234.   
  235.   
  236.   
  237.   
  238.   
  239. // MAC 地址比较    
  240.   
  241. bool cmpMAC(UCHAR *MAC1, UCHAR *MAC2);  
  242.   
  243.   
  244.   
  245. // MAC 地址复制    
  246.   
  247. void cpyMAC(UCHAR *MAC1, UCHAR *MAC2);  
  248.   
  249.   
  250.   
  251. // MAC 地址设置    
  252.   
  253. void setMAC(UCHAR *MAC, UCHAR ch);  
  254.   
  255.   
  256.   
  257. // IP 地址查询    
  258.   
  259. bool IPLookup(ULONG ipaddr, UCHAR *p);  
  260.   
  261.   
  262.   
  263. //  数据包捕获线程    
  264.   
  265. UINT Capture(PVOID pParam);  
  266.   
  267.   
  268.   
  269. //  获取本地接口MAC 地址线程    
  270.   
  271. UINT CaptureLocalARP(PVOID pParam);  
  272.   
  273.   
  274.   
  275. //  发送ARP 请求    
  276.   
  277. void ARPRequest(pcap_t *adhandle, UCHAR *srcMAC, ULONG srcIP, ULONG targetIP);  
  278.   
  279.   
  280.   
  281. //  查询路由表    
  282.   
  283. DWORD   RouteLookup(UINT   &ifNO, DWORD   desIP, CList   <RouteTable_t,  
  284.   
  285.     RouteTable_t&> *routeTable);  
  286.   
  287. //  处理ARP 数据包    
  288.   
  289. void ARPPacketProc(struct pcap_pkthdr *header, const u_char *pkt_data);  
  290.   
  291. //  处理IP 数据包    
  292.   
  293. void  IPPacketProc(IfInfo_t  *pIfInfo, struct  pcap_pkthdr  *header, const  u_char  
  294.   
  295.     *pkt_data);  
  296.   
  297. //  处理ICMP 数据包    
  298.   
  299. void  ICMPPacketProc(IfInfo_t  *pIfInfo, BYTE  type, BYTE  code, const  u_char  
  300.   
  301.     *pkt_data);  
  302.   
  303. //  检查IP 数据包头部校验和是否正确    
  304.   
  305. int IsChecksumRight(char * buffer);  
  306.   
  307.   
  308.   
  309. //  计算校验和    
  310.   
  311. unsigned short ChecksumCompute(unsigned short *buffer, int size);  
  312.   
  313. //下一部分  
  314.   
  315. //  获取本地接口MAC 地址线程    
  316.   
  317. UINT CaptureLocalARP(PVOID pParam)  
  318.   
  319. {  
  320.   
  321.     int                              res;  
  322.   
  323.     struct pcap_pkthdr  *header;  
  324.   
  325.     const u_char              *pkt_data;  
  326.   
  327.     IfInfo_t                  *pIfInfo;  
  328.   
  329.     ARPFrame_t                       *ARPFrame;  
  330.   
  331.     CString                          DisplayStr;  
  332.   
  333.   
  334.   
  335.     pIfInfo = (IfInfo_t *)pParam;  
  336.   
  337.   
  338.   
  339.     while (true)  
  340.   
  341.     {  
  342.   
  343.         Sleep(50);  
  344.   
  345.         res = pcap_next_ex(pIfInfo->adhandle, &header, &pkt_data);  
  346.   
  347.         //  超时    
  348.   
  349.         if (res == 0)  
  350.   
  351.             continue;  
  352.   
  353.         if (res > 0)  
  354.   
  355.         {  
  356.   
  357.             ARPFrame = (ARPFrame_t *)(pkt_data);  
  358.   
  359.             //  得到本接口的MAC 地址    
  360.   
  361.             if ((ARPFrame->FrameHeader.FrameType == htons(0x0806))  
  362.   
  363.                 && (ARPFrame->Operation == htons(0x0002))  
  364.   
  365.                 && (ARPFrame->SendIP == pIfInfo->ip[0].IPAddr))  
  366.   
  367.             {  
  368.   
  369.                 cpyMAC(pIfInfo->MACAddr, ARPFrame->SendHa);  
  370.   
  371.                 return 0;  
  372.   
  373.             }  
  374.   
  375.         }  
  376.   
  377.     }  
  378.   
  379. }  
  380.   
  381.   
  382.   
  383. void setMAC(UCHAR *MAC, UCHAR ch)  
  384.   
  385. {  
  386.   
  387.     for (int i = 0; i < 6; i++)  
  388.   
  389.     {  
  390.   
  391.         MAC[i] = ch;  
  392.   
  393.     }  
  394.   
  395.     return;  
  396.   
  397. }  
  398.   
  399.   
  400.   
  401.   
  402.   
  403. //  发送ARP 请求    
  404.   
  405. void ARPRequest(pcap_t  *adhandle, UCHAR *srcMAC, ULONG srcIP, ULONG  
  406.   
  407.     targetIP)  
  408.   
  409. {  
  410.   
  411.     ARPFrame_t   ARPFrame;  
  412.   
  413.     int                 i;  
  414.   
  415.   
  416.   
  417.     for (i = 0; i < 6; i++)  
  418.   
  419.     {  
  420.   
  421.         ARPFrame.FrameHeader.DesMAC[i] = 255;  
  422.   
  423.         ARPFrame.FrameHeader.SrcMAC[i] = srcMAC[i];  
  424.   
  425.         ARPFrame.SendHa[i] = srcMAC[i];  
  426.   
  427.         ARPFrame.RecvHa[i] = 0;  
  428.   
  429.     }  
  430.   
  431.   
  432.   
  433.     ARPFrame.FrameHeader.FrameType = htons(0x0806);  
  434.   
  435.     ARPFrame.HardwareType = htons(0x0001);  
  436.   
  437.     ARPFrame.ProtocolType = htons(0x0800);  
  438.   
  439.     ARPFrame.HLen = 6;  
  440.   
  441.     ARPFrame.PLen = 4;  
  442.   
  443.     ARPFrame.Operation = htons(0x0001);  
  444.   
  445.     ARPFrame.SendIP = srcIP;  
  446.   
  447.     ARPFrame.RecvIP = targetIP;  
  448.   
  449.   
  450.   
  451.     pcap_sendpacket(adhandle, (u_char *)&ARPFrame, sizeof(ARPFrame_t));  
  452.   
  453. }  
  454.   
  455.   
  456.   
  457. void cpyMAC(UCHAR *MAC1, UCHAR *MAC2)  
  458.   
  459. {  
  460.   
  461.     for (int i = 0; i < 6; i++)  
  462.   
  463.     {  
  464.   
  465.         MAC1[i] = MAC2[i];  
  466.   
  467.     }  
  468.   
  469. }  
  470.   
  471.   
  472.   
  473. //   比较两个MAC 地址是否相同    
  474.   
  475. bool cmpMAC(UCHAR *MAC1, UCHAR *MAC2)  
  476.   
  477. {  
  478.   
  479.     for (int i = 0; i < 6; i++)  
  480.   
  481.     {  
  482.   
  483.         if (MAC1[i] == MAC2[i])  
  484.   
  485.         {  
  486.   
  487.             continue;  
  488.   
  489.         }  
  490.   
  491.         else  
  492.   
  493.         {  
  494.   
  495.             return false;  
  496.   
  497.         }  
  498.   
  499.     }  
  500.   
  501.     return true;  
  502.   
  503. }  
  504.   
  505.   
  506.   
  507. //  把IP 地址转换成点分十进制形式    
  508.   
  509. CString IPntoa(ULONG nIPAddr)  
  510.   
  511. {  
  512.   
  513.     char          strbuf[50];  
  514.   
  515.     u_char               *p;  
  516.   
  517.     CString              str;  
  518.   
  519.   
  520.   
  521.     p = (u_char *)&nIPAddr;  
  522.   
  523.     sprintf_s(strbuf, "%03d.%03d.%03d.%03d", p[0], p[1], p[2], p[3]);  
  524.   
  525.     str = strbuf;  
  526.   
  527.     return str;  
  528.   
  529. }  
  530.   
  531.   
  532.   
  533.   
  534.   
  535. //  把MAC 地址转换成“%02X:%02X:%02X:%02X:%02X:%02X”的格式    
  536.   
  537. CString MACntoa(UCHAR *nMACAddr)  
  538.   
  539. {  
  540.   
  541.     char         strbuf[50];  
  542.   
  543.     CString             str;  
  544.   
  545.   
  546.   
  547.     sprintf_s(strbuf, "%02X:%02X:%02X:%02X:%02X:%02X", nMACAddr[0],  
  548.   
  549.         nMACAddr[1],  
  550.   
  551.         nMACAddr[2], nMACAddr[3], nMACAddr[4], nMACAddr[5]);  
  552.   
  553.     str = strbuf;  
  554.   
  555.     return str;  
  556.   
  557. }  
  558.   
  559.   
  560.   
  561. //  数据包捕获线程    
  562.   
  563. UINT Capture(PVOID pParam)  
  564.   
  565. {  
  566.   
  567.     int                               res;  
  568.   
  569.     IfInfo_t                   *pIfInfo;  
  570.   
  571.     struct pcap_pkthdr  *header;  
  572.   
  573.     const u_char               *pkt_data;  
  574.   
  575.   
  576.   
  577.     pIfInfo = (IfInfo_t *)pParam;  
  578.   
  579.   
  580.   
  581.     //  开始正式接收并处理帧    
  582.   
  583.     while (true)  
  584.   
  585.     {  
  586.   
  587.         res = pcap_next_ex(pIfInfo->adhandle, &header, &pkt_data);  
  588.   
  589.   
  590.   
  591.         if (res == 1)  
  592.   
  593.         {  
  594.   
  595.             FrameHeader_t               *fh;  
  596.   
  597.             fh = (FrameHeader_t *)pkt_data;  
  598.   
  599.             switch (ntohs(fh->FrameType))  
  600.   
  601.             {  
  602.   
  603.             case 0x0806:  
  604.   
  605.   
  606.   
  607.                 ARPFrame_t *ARPf;  
  608.   
  609.                 ARPf = (ARPFrame_t *)pkt_data;  
  610.   
  611.                 //TRACE1("    收到 ARP    包       源 IP   为: %d\n", ARPf->SendIP);  
  612.   
  613.   
  614.   
  615.                 // ARP 包,转到ARP 包处理函数    
  616.                 ARPPacketProc(header, pkt_data);  
  617.   
  618.                 break;  
  619.   
  620.   
  621.   
  622.             case 0x0800:  
  623.   
  624.   
  625.   
  626.                 IPFrame_t *IPf;  
  627.   
  628.                 IPf = (IPFrame_t*)pkt_data;  
  629.   
  630.                 //TRACE1("  收  到  IP 包 源IP 为:%d\n",IPf->IPHeader.SrcIP );    
  631.   
  632.   
  633.   
  634.                 // IP 包,转到IP 包处理函数    
  635.   
  636.                 IPPacketProc(pIfInfo, header, pkt_data);  
  637.   
  638.                 break;  
  639.   
  640.             default:  
  641.   
  642.                 break;  
  643.   
  644.             }  
  645.   
  646.         }  
  647.   
  648.         else if (res == 0)         //  超时    
  649.   
  650.         {  
  651.   
  652.             continue;  
  653.   
  654.         }  
  655.   
  656.         else  
  657.   
  658.         {  
  659.   
  660.             AfxMessageBox(_T("pcap_next_ex 函数出错!"));  
  661.   
  662.         }  
  663.   
  664.     }  
  665.   
  666.     return 0;  
  667.   
  668. }  
  669.   
  670.   
  671.   
  672. //  处理ARP 数据包    
  673.   
  674. void ARPPacketProc(struct pcap_pkthdr *header, const u_char *pkt_data)  
  675.   
  676. {  
  677.   
  678.     bool               flag;  
  679.   
  680.     ARPFrame_t               ARPf;  
  681.   
  682.     IPFrame_t                *IPf;  
  683.   
  684.     SendPacket_t  sPacket;  
  685.   
  686.     POSITION                 pos, CurrentPos;  
  687.   
  688.     IP_MAC_t                 ip_mac;  
  689.   
  690.     UCHAR                    macAddr[6];  
  691.   
  692.   
  693.   
  694.     ARPf = *(ARPFrame_t *)pkt_data;  
  695.   
  696.   
  697.   
  698.     if (ARPf.Operation == ntohs(0x0002))  
  699.   
  700.     {  
  701.   
  702.         pDlg->Logger.InsertString(-1, _T("收到ARP响应包"));  
  703.   
  704.         pDlg->Logger.InsertString(-1, (_T("      ARP ") + (IPntoa(ARPf.SendIP)) + _T(" -- ")  
  705.   
  706.             + MACntoa(ARPf.SendHa)));  
  707.   
  708.         // IP -MAC 地址映射表中已经存在该对应关系    
  709.   
  710.         if (IPLookup(ARPf.SendIP, macAddr))  
  711.   
  712.         {  
  713.   
  714.             pDlg->Logger.InsertString(-1, _T("      该对应关系已经存在于 IP - MAC 地址映射表中"));  
  715.   
  716.             return;  
  717.   
  718.         }  
  719.   
  720.         else  
  721.   
  722.         {  
  723.   
  724.             ip_mac.IPAddr = ARPf.SendIP;  
  725.   
  726.             memcpy(ip_mac.MACAddr, ARPf.SendHa, 6);  
  727.   
  728.             //  将IP-MAC 映射关系存入表中                                        
  729.   
  730.             IP_MAC.AddHead(ip_mac);  
  731.   
  732.   
  733.   
  734.             //   日志输出信息    
  735.   
  736.             pDlg->Logger.InsertString(-1, _T("      将该对应关系存入 IP -MAC 地址映射表中"));  
  737.   
  738.         }  
  739.   
  740.   
  741.   
  742.         mMutex.Lock(INFINITE);  
  743.   
  744.         do{  
  745.   
  746.   
  747.   
  748.             //  查看是否能转发缓存中的IP 数据报    
  749.   
  750.             flag = false;  
  751.   
  752.   
  753.   
  754.             //  没有需要处理的内容    
  755.   
  756.             if (SP.IsEmpty())  
  757.   
  758.             {  
  759.   
  760.                 break;  
  761.   
  762.             }  
  763.   
  764.   
  765.   
  766.             //  遍历转发缓存区    
  767.   
  768.             pos = SP.GetHeadPosition();  
  769.   
  770.             for (int i = 0; i < SP.GetCount(); i++)  
  771.   
  772.             {  
  773.   
  774.                 CurrentPos = pos;  
  775.   
  776.                 sPacket = SP.GetNext(pos);  
  777.   
  778.   
  779.   
  780.                 if (sPacket.TargetIP == ARPf.SendIP)  
  781.   
  782.                 {  
  783.   
  784.                     IPf = (IPFrame_t *)sPacket.PktData;  
  785.   
  786.                     cpyMAC(IPf->FrameHeader.DesMAC, ARPf.SendHa);  
  787.   
  788.   
  789.   
  790.                     for (int t = 0; t < 6; t++)  
  791.   
  792.                     {  
  793.   
  794.                         IPf->FrameHeader.SrcMAC[t] =  
  795.   
  796.                             IfInfo[sPacket.IfNo].MACAddr[t];  
  797.   
  798.                     }  
  799.   
  800.                     //  发送IP 数据包    
  801.   
  802.                     pcap_sendpacket(IfInfo[sPacket.IfNo].adhandle, (u_char  
  803.   
  804.                         *)sPacket.PktData, sPacket.len);  
  805.   
  806.   
  807.   
  808.                     SP.RemoveAt(CurrentPos);  
  809.   
  810.   
  811.   
  812.                     //   日志输出信息    
  813.   
  814.                     pDlg->Logger.InsertString(-1, _T("      转发缓存区中目的地址是该MAC 地址的IP 数据包"));  
  815.   
  816.                     pDlg->Logger.InsertString(-1, (_T("          发送 IP  数据包:") + IPntoa(IPf->IPHeader.SrcIP)  
  817.                         + "->"  
  818.                         + IPntoa(IPf->IPHeader.DstIP) + "         " +  
  819.   
  820.                         MACntoa(IPf->FrameHeader.SrcMAC)  
  821.   
  822.                         + "->" + MACntoa(IPf->FrameHeader.DesMAC)));  
  823.   
  824.   
  825.   
  826.                     flag = true;  
  827.   
  828.                     break;  
  829.   
  830.                 }  
  831.   
  832.             }  
  833.   
  834.         } while (flag);  
  835.   
  836.   
  837.   
  838.         mMutex.Unlock();  
  839.   
  840.     }  
  841.   
  842. }  
  843.   
  844.   
  845.   
  846. //  查询IP-MAC 映射表    
  847.   
  848. bool IPLookup(ULONG ipaddr, UCHAR *p)  
  849.   
  850. {  
  851.   
  852.     IP_MAC_t             ip_mac;  
  853.   
  854.     POSITION             pos;  
  855.   
  856.   
  857.   
  858.     if (IP_MAC.IsEmpty()) return false;  
  859.   
  860.   
  861.   
  862.     pos = IP_MAC.GetHeadPosition();  
  863.   
  864.     for (int i = 0; i < IP_MAC.GetCount(); i++)  
  865.   
  866.     {  
  867.   
  868.         ip_mac = IP_MAC.GetNext(pos);  
  869.   
  870.         if (ipaddr == ip_mac.IPAddr)  
  871.   
  872.         {  
  873.   
  874.             for (int j = 0; j < 6; j++)  
  875.   
  876.             {  
  877.   
  878.                 p[j] = ip_mac.MACAddr[j];  
  879.   
  880.             }  
  881.   
  882.             return true;  
  883.   
  884.         }  
  885.   
  886.     }  
  887.   
  888.     return false;  
  889.   
  890. }  
  891.   
  892.   
  893.   
  894. //  处理IP 数据包    
  895.   
  896. void  IPPacketProc(IfInfo_t  *pIfInfo, struct  pcap_pkthdr  *header, const  u_char  
  897.   
  898.     *pkt_data)  
  899.   
  900. {  
  901.   
  902.     IPFrame_t                *IPf;  
  903.   
  904.     SendPacket_t  sPacket;  
  905.   
  906.   
  907.   
  908.     IPf = (IPFrame_t *)pkt_data;  
  909.   
  910.   
  911.   
  912.     pDlg->Logger.InsertString(-1, (_T("    收 到  IP 数 据 包 :") +  
  913.   
  914.         IPntoa(IPf->IPHeader.SrcIP) + "->"  
  915.   
  916.         + IPntoa(IPf->IPHeader.DstIP)));  
  917.   
  918.   
  919.   
  920.     // ICMP 超时    
  921.   
  922.     if (IPf->IPHeader.TTL <= 0)  
  923.   
  924.     {  
  925.   
  926.         ICMPPacketProc(pIfInfo, 11, 0, pkt_data);  
  927.   
  928.         return;  
  929.   
  930.     }  
  931.   
  932.   
  933.   
  934.     IPHeader_t *IpHeader = &(IPf->IPHeader);  
  935.   
  936.     // ICMP 差错    
  937.   
  938.     if (IsChecksumRight((char *)IpHeader) == 0)  
  939.   
  940.     {  
  941.   
  942.         //   日志输出信息    
  943.   
  944.         pDlg->Logger.InsertString(-1, _T("      IP 数据包包头校验和错误,丢弃数据包"));  
  945.   
  946.         return;  
  947.   
  948.     }  
  949.   
  950.   
  951.   
  952.     //  路由查询    
  953.   
  954.     DWORD nextHop;                 //  经过路由选择算法得到的下一站目的IP 地址    
  955.   
  956.     UINT ifNo;                     //  下一跳的接口序号    
  957.   
  958.     //  路由查询    
  959.   
  960.     if ((nextHop = RouteLookup(ifNo, IPf->IPHeader.DstIP, &RouteTable)) == -1)  
  961.   
  962.     {  
  963.   
  964.   
  965.   
  966.         // ICMP  目的不可达    
  967.   
  968.         ICMPPacketProc(pIfInfo, 3, 0, pkt_data);  
  969.   
  970.         return;  
  971.   
  972.     }  
  973.   
  974.     else  
  975.   
  976.     {  
  977.   
  978.         sPacket.IfNo = ifNo;  
  979.   
  980.         sPacket.TargetIP = nextHop;  
  981.   
  982.   
  983.   
  984.         cpyMAC(IPf->FrameHeader.SrcMAC, IfInfo[sPacket.IfNo].MACAddr);  
  985.   
  986.   
  987.   
  988.         // TTL 减1    
  989.   
  990.         IPf->IPHeader.TTL -= 1;  
  991.   
  992.   
  993.   
  994.         unsigned short check_buff[sizeof(IPHeader_t)];  
  995.   
  996.         //  设IP 头中的校验和为0    
  997.   
  998.         IPf->IPHeader.Checksum = 0;  
  999.   
  1000.   
  1001.   
  1002.         memset(check_buff, 0, sizeof(IPHeader_t));  
  1003.   
  1004.         IPHeader_t * ip_header = &(IPf->IPHeader);  
  1005.   
  1006.         memcpy(check_buff, ip_header, sizeof(IPHeader_t));  
  1007.   
  1008.   
  1009.   
  1010.         //  计算IP 头部校验和    
  1011.   
  1012.         IPf->IPHeader.Checksum = ChecksumCompute(check_buff,  
  1013.   
  1014.             sizeof(IPHeader_t));  
  1015.   
  1016.   
  1017.   
  1018.         // IP-MAC 地址映射表中存在该映射关系    
  1019.   
  1020.         if (IPLookup(sPacket.TargetIP, IPf->FrameHeader.DesMAC))  
  1021.   
  1022.         {  
  1023.   
  1024.             memcpy(sPacket.PktData, pkt_data, header->len);  
  1025.   
  1026.             sPacket.len = header->len;  
  1027.   
  1028.             if (pcap_sendpacket(IfInfo[sPacket.IfNo].adhandle, (u_char *)  
  1029.   
  1030.                 sPacket.PktData, sPacket.len) != 0)  
  1031.   
  1032.             {  
  1033.   
  1034.                 //  错误处理    
  1035.   
  1036.                 AfxMessageBox(_T("发送IP 数据包时出错!"));  
  1037.   
  1038.                 return;  
  1039.   
  1040.             }  
  1041.   
  1042.   
  1043.   
  1044.             //   日志输出信息    
  1045.   
  1046.             pDlg->Logger.InsertString(-1, _T("  转发IP 数据包:"));  
  1047.   
  1048.             pDlg->Logger.InsertString(-1, (_T("         ") + IPntoa(IPf->IPHeader.SrcIP)  
  1049.   
  1050.                 + "->"  
  1051.   
  1052.                 + IPntoa(IPf->IPHeader.DstIP) + _T("            ") +  
  1053.   
  1054.                 MACntoa(IPf->FrameHeader.SrcMAC)  
  1055.   
  1056.                 + "->" + MACntoa(IPf->FrameHeader.DesMAC)));  
  1057.   
  1058.         }  
  1059.   
  1060.         // IP-MAC 地址映射表中不存在该映射关系    
  1061.   
  1062.         else  
  1063.   
  1064.         {  
  1065.   
  1066.             if (SP.GetCount() < 65530)                   //  存入缓存队列    
  1067.   
  1068.             {  
  1069.   
  1070.                 sPacket.len = header->len;  
  1071.   
  1072.                 //  将需要转发的数据报存入缓存区    
  1073.   
  1074.                 memcpy(sPacket.PktData, pkt_data, header->len);  
  1075.   
  1076.   
  1077.   
  1078.                 //  在某一时刻只允许一个线程维护链表    
  1079.   
  1080.                 mMutex.Lock(INFINITE);  
  1081.   
  1082.   
  1083.   
  1084.                 sPacket.n_mTimer = TimerCount;  
  1085.   
  1086.                 if (TimerCount++ > 65533)  
  1087.   
  1088.                 {  
  1089.   
  1090.                     TimerCount = 1;  
  1091.   
  1092.                 }  
  1093.   
  1094.                 pDlg->SetTimer(sPacket.n_mTimer, 10000, NULL);  
  1095.   
  1096.                 SP.AddTail(sPacket);  
  1097.   
  1098.   
  1099.   
  1100.                 mMutex.Unlock();  
  1101.   
  1102.   
  1103.   
  1104.                 //   日志输出信息    
  1105.   
  1106.                 pDlg->Logger.InsertString(-1, _T("      缺少目的MAC 地址,将IP数据包存入转发缓冲区"));  
  1107.   
  1108.                 pDlg->Logger.InsertString(-1, (_T("      存入转发缓冲区的数据包为:") + IPntoa(IPf->IPHeader.SrcIP)  
  1109.   
  1110.   
  1111.                     + "->" + IPntoa(IPf->IPHeader.DstIP) + "     " +  
  1112.   
  1113.                     MACntoa(IPf->FrameHeader.SrcMAC)  
  1114.   
  1115.                     + "->xx:xx:xx:xx:xx:xx"));  
  1116.   
  1117.                 pDlg->Logger.InsertString(-1, _T("      发送ARP 请求"));  
  1118.   
  1119.   
  1120.   
  1121.                 //  发送ARP 请求    
  1122.   
  1123.                 ARPRequest(IfInfo[sPacket.IfNo].adhandle,  
  1124.   
  1125.                     IfInfo[sPacket.IfNo].MACAddr,  
  1126.   
  1127.                     IfInfo[sPacket.IfNo].ip[1].IPAddr, sPacket.TargetIP);  
  1128.   
  1129.             }  
  1130.   
  1131.             else  //  如缓存队列太长,抛弃该报    
  1132.   
  1133.             {  
  1134.   
  1135.                 //   日志输出信息    
  1136.   
  1137.                 pDlg->Logger.InsertString(-1, _T("转发缓冲区溢出,丢弃IP数据包"));  
  1138.   
  1139.                 pDlg->Logger.InsertString(-1, (_T("      丢弃的IP 数据包为:") +  
  1140.   
  1141.                     IPntoa(IPf->IPHeader.SrcIP) + "->"  
  1142.   
  1143.                     + IPntoa(IPf->IPHeader.DstIP) + "          " +  
  1144.   
  1145.                     MACntoa(IPf->FrameHeader.SrcMAC)  
  1146.   
  1147.                     + "->xx:xx:xx:xx:xx:xx"));  
  1148.   
  1149.             }  
  1150.   
  1151.         }  
  1152.   
  1153.     }  
  1154.   
  1155.   
  1156.   
  1157. }  
  1158.   
  1159.   
  1160.   
  1161. //  判断IP 数据包头部校验和是否正确    
  1162.   
  1163. int IsChecksumRight(char * buffer)  
  1164.   
  1165. {  
  1166.   
  1167.     //  获得IP 头内容    
  1168.   
  1169.     IPHeader_t * ip_header = (IPHeader_t *)buffer;  
  1170.   
  1171.     //  备份原来的校验和    
  1172.   
  1173.     unsigned short checksumBuf = ip_header->Checksum;  
  1174.   
  1175.     unsigned short check_buff[sizeof(IPHeader_t)];  
  1176.   
  1177.     //  设IP 头中的校验和为0    
  1178.   
  1179.     ip_header->Checksum = 0;  
  1180.   
  1181.   
  1182.   
  1183.     memset(check_buff, 0, sizeof(IPHeader_t));  
  1184.   
  1185.     memcpy(check_buff, ip_header, sizeof(IPHeader_t));  
  1186.   
  1187.   
  1188.   
  1189.     //  计算IP 头部校验和    
  1190.   
  1191.     ip_header->Checksum = ChecksumCompute(check_buff, sizeof(IPHeader_t));  
  1192.   
  1193.   
  1194.   
  1195.     //  与备份的校验和进行比较    
  1196.   
  1197.     if (ip_header->Checksum == checksumBuf)  
  1198.   
  1199.     {  
  1200.   
  1201.         return 1;  
  1202.   
  1203.     }  
  1204.   
  1205.     else  
  1206.   
  1207.     {  
  1208.   
  1209.         return 0;  
  1210.   
  1211.     }  
  1212.   
  1213. }  
  1214.   
  1215.   
  1216.   
  1217. //  查询路由表    
  1218.   
  1219. DWORD   RouteLookup(UINT   &ifNO, DWORD   desIP, CList   <RouteTable_t,  
  1220.   
  1221.     RouteTable_t&> *routeTable)  
  1222.   
  1223. {  
  1224.   
  1225.     // desIP 为网络序    
  1226.   
  1227.     DWORD MaxMask = 0; //  获得最大的子网掩码的地址,没有获得时初始为 - 1  
  1228.   
  1229.     int          Index = -1;              //  获得最大的子网掩码的地址对应的路由表 索引,以便获得下一站路由器的地址  
  1230.   
  1231.   
  1232.     POSITION                 pos;  
  1233.   
  1234.     RouteTable_t   rt;  
  1235.   
  1236.     DWORD tmp;  
  1237.   
  1238.   
  1239.   
  1240.     pos = routeTable->GetHeadPosition();  
  1241.   
  1242.     for (int i = 0; i < routeTable->GetCount(); i++)  
  1243.   
  1244.     {  
  1245.   
  1246.         rt = routeTable->GetNext(pos);  
  1247.   
  1248.         if ((desIP & rt.Mask) == rt.DstIP)  
  1249.   
  1250.         {  
  1251.   
  1252.   
  1253.   
  1254.             Index = i;  
  1255.   
  1256.   
  1257.   
  1258.             if (rt.Mask >= MaxMask)  
  1259.   
  1260.             {  
  1261.   
  1262.                 ifNO = rt.IfNo;  
  1263.   
  1264.   
  1265.   
  1266.                 if (rt.NextHop == 0)                //  直接投递    
  1267.   
  1268.                 {  
  1269.   
  1270.                     tmp = desIP;  
  1271.   
  1272.                 }  
  1273.   
  1274.                 else  
  1275.   
  1276.                 {  
  1277.   
  1278.                     tmp = rt.NextHop;  
  1279.   
  1280.                 }  
  1281.   
  1282.             }  
  1283.   
  1284.         }  
  1285.   
  1286.     }  
  1287.   
  1288.   
  1289.   
  1290.     if (Index == -1)                                    //   目的不可达    
  1291.   
  1292.     {  
  1293.   
  1294.         return -1;  
  1295.   
  1296.     }  
  1297.   
  1298.     else           //  找到了下一跳地址    
  1299.   
  1300.     {  
  1301.   
  1302.         return tmp;  
  1303.   
  1304.     }  
  1305.   
  1306. }  
  1307.   
  1308.   
  1309.   
  1310. //  发送ICMP 数据包    
  1311.   
  1312. void  ICMPPacketProc(IfInfo_t  *pIfInfo, BYTE  type, BYTE  code, const  u_char  
  1313.   
  1314.     *pkt_data)  
  1315.   
  1316. {  
  1317.   
  1318.     u_char * ICMPBuf = new u_char[70];  
  1319.   
  1320.   
  1321.   
  1322.     //  填充帧首部    
  1323.   
  1324.     memcpy(((FrameHeader_t                        *)ICMPBuf)->DesMAC, ((FrameHeader_t  
  1325.   
  1326.         *)pkt_data)->SrcMAC, 6);  
  1327.   
  1328.     memcpy(((FrameHeader_t               *)ICMPBuf)->SrcMAC, ((FrameHeader_t  
  1329.   
  1330.         *)pkt_data)->DesMAC, 6);  
  1331.   
  1332.     ((FrameHeader_t *)ICMPBuf)->FrameType = htons(0x0800);  
  1333.   
  1334.   
  1335.   
  1336.     //  填充IP 首部    
  1337.   
  1338.     ((IPHeader_t           *)(ICMPBuf + 14))->Ver_HLen = ((IPHeader_t  
  1339.   
  1340.         *)(pkt_data + 14))->Ver_HLen;  
  1341.   
  1342.     ((IPHeader_t             *)(ICMPBuf + 14))->TOS = ((IPHeader_t  
  1343.   
  1344.         *)(pkt_data + 14))->TOS;  
  1345.   
  1346.     ((IPHeader_t *)(ICMPBuf + 14))->TotalLen = htons(56);  
  1347.   
  1348.     ((IPHeader_t *)(ICMPBuf + 14))->ID = ((IPHeader_t *)(pkt_data + 14))->ID;  
  1349.   
  1350.     ((IPHeader_t          *)(ICMPBuf + 14))->Flag_Segment = ((IPHeader_t  
  1351.   
  1352.         *)(pkt_data + 14))->Flag_Segment;  
  1353.   
  1354.     ((IPHeader_t *)(ICMPBuf + 14))->TTL = 64;  
  1355.   
  1356.     ((IPHeader_t *)(ICMPBuf + 14))->Protocol = 1;  
  1357.   
  1358.     ((IPHeader_t             *)(ICMPBuf + 14))->SrcIP = ((IPHeader_t  
  1359.   
  1360.         *)(pkt_data + 14))->DstIP;  
  1361.   
  1362.     ((IPHeader_t             *)(ICMPBuf + 14))->DstIP = ((IPHeader_t  
  1363.   
  1364.         *)(pkt_data + 14))->SrcIP;  
  1365.   
  1366.     ((IPHeader_t                      *)(ICMPBuf + 14))->Checksum =  
  1367.   
  1368.         htons(ChecksumCompute((unsigned short *)(ICMPBuf + 14), 20));  
  1369.   
  1370.   
  1371.   
  1372.     //  填充ICMP 首部    
  1373.   
  1374.     ((ICMPHeader_t *)(ICMPBuf + 34))->Type = type;  
  1375.   
  1376.     ((ICMPHeader_t *)(ICMPBuf + 34))->Code = code;  
  1377.   
  1378.     ((ICMPHeader_t *)(ICMPBuf + 34))->Id = 0;  
  1379.   
  1380.     ((ICMPHeader_t *)(ICMPBuf + 34))->Sequence = 0;  
  1381.   
  1382.     ((ICMPHeader_t                       *)(ICMPBuf + 34))->Checksum =  
  1383.   
  1384.         htons(ChecksumCompute((unsigned short *)(ICMPBuf + 34), 8));  
  1385.   
  1386.   
  1387.   
  1388.     //  填充数据    
  1389.   
  1390.     memcpy((u_char *)(ICMPBuf + 42), (IPHeader_t *)(pkt_data + 14), 20);  
  1391.   
  1392.     memcpy((u_char *)(ICMPBuf + 62), (u_char *)(pkt_data + 34), 8);  
  1393.   
  1394.   
  1395.   
  1396.     //  发送数据包    
  1397.   
  1398.     pcap_sendpacket(pIfInfo->adhandle, (u_char *)ICMPBuf, 70);  
  1399.   
  1400.   
  1401.   
  1402.     //   日志输出信息    
  1403.   
  1404.     if (type == 11)  
  1405.   
  1406.     {  
  1407.   
  1408.         pDlg->Logger.InsertString(-1, _T("      发送ICMP 超时数据包:"));  
  1409.   
  1410.     }  
  1411.   
  1412.     if (type == 3)  
  1413.   
  1414.     {  
  1415.   
  1416.         pDlg->Logger.InsertString(-1, _T("   发送ICMP 目的不可达数据包:"));  
  1417.   
  1418.     }  
  1419.   
  1420.     pDlg->Logger.InsertString(-1, (_T("         ICMP       ->") + IPntoa(((IPHeader_t  
  1421.   
  1422.         *)(ICMPBuf + 14))->DstIP)  
  1423.   
  1424.         + "-" + MACntoa(((FrameHeader_t *)ICMPBuf)->DesMAC)));  
  1425.   
  1426.   
  1427.   
  1428.     delete[] ICMPBuf;  
  1429.   
  1430. }  
  1431.   
  1432. //  计算校验和    
  1433.   
  1434. unsigned short ChecksumCompute(unsigned short * buffer, int size)  
  1435.   
  1436. {  
  1437.   
  1438.     // 32 位,延迟进位    
  1439.   
  1440.     unsigned long cksum = 0;  
  1441.   
  1442.     while (size > 1)  
  1443.   
  1444.     {  
  1445.   
  1446.         cksum += *buffer++;  
  1447.   
  1448.         // 16 位相加    
  1449.   
  1450.         size -= sizeof(unsigned short);  
  1451.   
  1452.     }  
  1453.   
  1454.     if (size)  
  1455.   
  1456.     {  
  1457.   
  1458.         //  最后可能有单独8 位    
  1459.   
  1460.         cksum += *(unsigned char *)buffer;  
  1461.   
  1462.     }  
  1463.   
  1464.     //  将高 16 位进位加至低16 位    
  1465.   
  1466.     cksum = (cksum >> 16) + (cksum & 0xffff);  
  1467.   
  1468.     cksum += (cksum >> 16);  
  1469.   
  1470.     //  取反    
  1471.   
  1472.     return (unsigned short)(~cksum);  
  1473.   
  1474.   
  1475. }  
  1476.   
  1477. // 用于应用程序“关于”菜单项的 CAboutDlg 对话框  
  1478.   
  1479. class CAboutDlg : public CDialogEx  
  1480. {  
  1481. public:  
  1482.     CAboutDlg();  
  1483.   
  1484.     // 对话框数据  
  1485.     enum { IDD = IDD_ABOUTBOX };  
  1486.   
  1487. protected:  
  1488.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持  
  1489.   
  1490.     // 实现  
  1491. protected:  
  1492.     DECLARE_MESSAGE_MAP()  
  1493. };  
  1494.   
  1495. CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)  
  1496. {  
  1497. }  
  1498.   
  1499. void CAboutDlg::DoDataExchange(CDataExchange* pDX)  
  1500. {  
  1501.     CDialogEx::DoDataExchange(pDX);  
  1502. }  
  1503.   
  1504. BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)  
  1505. END_MESSAGE_MAP()  
  1506.   
  1507.   
  1508. // CVCRouterDlg 对话框  
  1509.   
  1510.   
  1511.   
  1512. CVCRouterDlg::CVCRouterDlg(CWnd* pParent /*=NULL*/)  
  1513. : CDialogEx(CVCRouterDlg::IDD, pParent)  
  1514. {  
  1515.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  1516. }  
  1517.   
  1518. void CVCRouterDlg::DoDataExchange(CDataExchange* pDX)  
  1519. {  
  1520.     CDialogEx::DoDataExchange(pDX);  
  1521.     DDX_Control(pDX, LOGGER_LIST, Logger);  
  1522.     DDX_Control(pDX, ROUTER_LIST, m_RouteTable);  
  1523.     DDX_Control(pDX, IDC_NEXTHOP, m_NextHop);  
  1524.     DDX_Control(pDX, IDC_NETMASK, m_Mask);  
  1525.     DDX_Control(pDX, IDC_IPADDRESS, m_Destination);  
  1526. }  
  1527.   
  1528. BEGIN_MESSAGE_MAP(CVCRouterDlg, CDialogEx)  
  1529.     ON_WM_SYSCOMMAND()  
  1530.     ON_WM_PAINT()  
  1531.     ON_WM_QUERYDRAGICON()  
  1532.     ON_BN_CLICKED(ONSTART_BUTTON, &CVCRouterDlg::OnStartClickedButton)  
  1533.     ON_BN_CLICKED(ONSTOP_BUTTON, &CVCRouterDlg::OnBnClickedButton)  
  1534.     ON_BN_CLICKED(ADD_ROUTER_BUTTON, &CVCRouterDlg::OnAddRouterButton)  
  1535.     ON_BN_CLICKED(DELETE_ROUTER_BUTTON, &CVCRouterDlg::OnDeleteRouterButton)  
  1536.     ON_WM_DESTROY()  
  1537.     ON_WM_TIMER()  
  1538. END_MESSAGE_MAP()  
  1539.   
  1540.   
  1541. // CVCRouterDlg 消息处理程序  
  1542.   
  1543. BOOL CVCRouterDlg::OnInitDialog()  
  1544. {  
  1545.     CDialogEx::OnInitDialog();  
  1546.   
  1547.     CVCRouterApp* pApp = (CVCRouterApp*)AfxGetApp();  
  1548.     pDlg = (CVCRouterDlg*)pApp->m_pMainWnd;  
  1549.     // 将“关于...”菜单项添加到系统菜单中。  
  1550.   
  1551.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  1552.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  1553.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  1554.   
  1555.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  1556.     if (pSysMenu != NULL)  
  1557.     {  
  1558.         BOOL bNameValid;  
  1559.         CString strAboutMenu;  
  1560.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  1561.         ASSERT(bNameValid);  
  1562.         if (!strAboutMenu.IsEmpty())  
  1563.         {  
  1564.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  1565.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  1566.         }  
  1567.     }  
  1568.   
  1569.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  1570.     //  执行此操作  
  1571.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  1572.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  1573.   
  1574.     // TODO:  在此添加额外的初始化代码  
  1575.   
  1576.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  1577. }  
  1578.   
  1579. void CVCRouterDlg::OnSysCommand(UINT nID, LPARAM lParam)  
  1580. {  
  1581.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)  
  1582.     {  
  1583.         CAboutDlg dlgAbout;  
  1584.         dlgAbout.DoModal();  
  1585.     }  
  1586.     else  
  1587.     {  
  1588.         CDialogEx::OnSysCommand(nID, lParam);  
  1589.     }  
  1590. }  
  1591.   
  1592. // 如果向对话框添加最小化按钮,则需要下面的代码  
  1593. //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,  
  1594. //  这将由框架自动完成。  
  1595.   
  1596. void CVCRouterDlg::OnPaint()  
  1597. {  
  1598.     if (IsIconic())  
  1599.     {  
  1600.         CPaintDC dc(this); // 用于绘制的设备上下文  
  1601.   
  1602.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);  
  1603.   
  1604.         // 使图标在工作区矩形中居中  
  1605.         int cxIcon = GetSystemMetrics(SM_CXICON);  
  1606.         int cyIcon = GetSystemMetrics(SM_CYICON);  
  1607.         CRect rect;  
  1608.         GetClientRect(&rect);  
  1609.         int x = (rect.Width() - cxIcon + 1) / 2;  
  1610.         int y = (rect.Height() - cyIcon + 1) / 2;  
  1611.   
  1612.         // 绘制图标  
  1613.         dc.DrawIcon(x, y, m_hIcon);  
  1614.     }  
  1615.     else  
  1616.     {  
  1617.         CDialogEx::OnPaint();  
  1618.     }  
  1619. }  
  1620.   
  1621. //当用户拖动最小化窗口时系统调用此函数取得光标  
  1622. //显示。  
  1623. HCURSOR CVCRouterDlg::OnQueryDragIcon()  
  1624. {  
  1625.     return static_cast<HCURSOR>(m_hIcon);  
  1626. }  
  1627.   
  1628.   
  1629.   
  1630. void CVCRouterDlg::OnStartClickedButton()  
  1631. {  
  1632.     // TODO:  在此添加控件通知处理程序代码  
  1633.     pcap_if_t *alldevs, *d;  
  1634.     pcap_addr_t *a;  
  1635.     struct bpf_program fcode;  
  1636.     char errbuf[PCAP_ERRBUF_SIZE], strbuf[1000];  
  1637.     int i, j, k;  
  1638.     ip_t ipaddr;  
  1639.     UCHAR srcMAC[6];  
  1640.     ULONG srcIP;  
  1641.     SetTimer(3999, 10000, 0);  
  1642.     // 获得本机的设备列表  
  1643.     if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* 无 需 认 证 */,  
  1644.         &alldevs, errbuf) == -1)  
  1645.     {  
  1646.         // 错误,返回错误信息  
  1647.         sprintf_s(strbuf, "pcap_findalldevs_ex 错误: %s", errbuf);  
  1648.         MessageBox((LPCTSTR)strbuf);  
  1649.         PostMessage(WM_QUIT, 0, 0);  
  1650.     }  
  1651.     i = 0;  
  1652.     j = 0;  
  1653.     k = 0;  
  1654.     // 获取 IP 地址信息  
  1655.     for (d = alldevs; d != NULL; d = d->next)  
  1656.     {  
  1657.         if (d->addresses != NULL) // 排除集成 modem 的影响(没有 IP 地址)  
  1658.         {  
  1659.             // 得到一个有效的接口和其 IP 地址列表  
  1660.             IfInfo[i].DeviceName = d->name;  
  1661.             IfInfo[i].Description = d->description;  
  1662.             for (a = d->addresses; a; a = a->next)  
  1663.             {  
  1664.                 if (a->addr->sa_family == AF_INET)  
  1665.                 {  
  1666.                     ipaddr.IPAddr = (((struct sockaddr_in  
  1667.                         *)a->addr)->sin_addr.s_addr);  
  1668.                     ipaddr.IPMask = (((struct sockaddr_in  
  1669.                         *)a->netmask)->sin_addr.s_addr);  
  1670.                     IfInfo[i].ip.Add(ipaddr);  
  1671.                     j++;  
  1672.                 }  
  1673.             }  
  1674.             if (i == MAX_IF) // 最多处理 MAX_IF 个接口  
  1675.             {  
  1676.                 break;  
  1677.             }  
  1678.             else  
  1679.             {  
  1680.                 i++;  
  1681.             }  
  1682.         }  
  1683.     }  
  1684.     // 不符合路由器 IP 地址数目要求  
  1685.     if (j < 2)  
  1686.     {  
  1687.         MessageBox("该路由程序要求本地主机至少应具有 2 个 IP 地址");  
  1688.         PostMessage(WM_QUIT, 0, 0);  
  1689.     }  
  1690.     // 保存实际的网卡数  
  1691.     IfCount = i;  
  1692.     // 打开接口  
  1693.     for (i = 0; i < IfCount; i++)  
  1694.     {  
  1695.         if ((IfInfo[i].adhandle = pcap_open(IfInfo[i].DeviceName, // 设备名  
  1696.             65536, // 最大包长度  
  1697.             PCAP_OPENFLAG_PROMISCUOUS,  
  1698.             // 混杂模式  
  1699.             1000, // 超时时间  
  1700.             NULL, // 远程认证  
  1701.             errbuf // 错误缓存  
  1702.             )) == NULL)  
  1703.         {  
  1704.             // 错误,显示错误信息  
  1705.             sprintf_s(strbuf, " 接 口 未 能 打 开 。 WinPcap 不 支 持 %s 。 ",  
  1706.                 IfInfo[i].DeviceName);  
  1707.             MessageBox((LPCTSTR)strbuf);  
  1708.             PostMessage(WM_QUIT, 0, 0);  
  1709.         }  
  1710.     }  
  1711.     // 开启数据包捕获线程,获取本地接口的 MAC 地址,线程数目为网卡个数  
  1712.     CWinThread* pthread;  
  1713.     for (i = 0; i < IfCount; i++)  
  1714.     {  
  1715.         pthread = AfxBeginThread(CaptureLocalARP, &IfInfo[i],  
  1716.             THREAD_PRIORITY_NORMAL);  
  1717.         if (!pthread)  
  1718.         {  
  1719.             MessageBox(_T("创建数据包捕获线程失败! "));  
  1720.             PostMessage(WM_QUIT, 0, 0);  
  1721.         }  
  1722.     }  
  1723.     // 将列表中网卡硬件地址清 0  
  1724.     for (i = 0; i < IfCount; i++)  
  1725.     {  
  1726.         setMAC(IfInfo[i].MACAddr, 0);  
  1727.     }  
  1728.     // 为得到真实网卡地址,使用虚假的 MAC 地址和 IP 地址向本机发送 ARP 请求  
  1729.     setMAC(srcMAC, 66); // 设置虚假的 MAC 地址  
  1730.     srcIP = inet_addr("112.112.112.112"); // 设置虚假的 IP 地址  
  1731.     for (i = 0; i < IfCount; i++)  
  1732.     {  
  1733.         ARPRequest(IfInfo[i].adhandle, srcMAC, srcIP, IfInfo[i].ip[0].IPAddr);  
  1734.     }  
  1735.     // 确保所有接口的 MAC 地址完全收到  
  1736.     setMAC(srcMAC, 0);  
  1737.     do {  
  1738.         Sleep(1000);  
  1739.         k = 0;  
  1740.         for (i = 0; i < IfCount; i++)  
  1741.         {  
  1742.             if (!cmpMAC(IfInfo[i].MACAddr, srcMAC))  
  1743.             {  
  1744.                 k++;  
  1745.                 continue;  
  1746.             }  
  1747.             else  
  1748.             {  
  1749.                 break;  
  1750.             }  
  1751.         }  
  1752.     } while (!((j++ > 10) || (k == IfCount)));  
  1753.     if (k != IfCount)  
  1754.     {  
  1755.         MessageBox(_T("至少有一个接口的 MAC 地址没能得到! "));  
  1756.         PostMessage(WM_QUIT, 0, 0);  
  1757.     }  
  1758.     // 日志输出接口信息  
  1759.     for (i = 0; i < IfCount; i++)  
  1760.     {  
  1761.         Logger.InsertString(-1, _T("接口:"));  
  1762.         Logger.InsertString(-1, _T(" 设备名: ") + IfInfo[i].DeviceName);  
  1763.         Logger.InsertString(-1, _T(" 设备描述: ") + IfInfo[i].Description);  
  1764.         Logger.InsertString(-1, (_T("MAC 地址:") + MACntoa(IfInfo[i].MACAddr)));  
  1765.         for (j = 0; j < IfInfo[i].ip.GetSize(); j++)  
  1766.         {  
  1767.             Logger.InsertString(-1, (_T("IP 地址: ") + IPntoa(IfInfo[i].ip[j].IPAddr)));  
  1768.         }  
  1769.     }  
  1770.     // 初始化路由表并显示  
  1771.     RouteTable_t rt;  
  1772.     for (i = 0; i < IfCount; i++)  
  1773.     {  
  1774.         for (j = 0; j < IfInfo[i].ip.GetSize(); j++)  
  1775.         {  
  1776.             rt.IfNo = i;  
  1777.             rt.DstIP = IfInfo[i].ip[j].IPAddr & IfInfo[i].ip[j].IPMask;  
  1778.             rt.Mask = IfInfo[i].ip[j].IPMask;  
  1779.             rt.NextHop = 0; // 直接投递  
  1780.             RouteTable.AddTail(rt);  
  1781.             m_RouteTable.InsertString(-1, IPntoa(rt.Mask) + " -- " +  
  1782.                 IPntoa(rt.DstIP) + " -- " + IPntoa(rt.NextHop) + " (直接投递)");  
  1783.         }  
  1784.     }  
  1785.     // 设置过滤规则:仅仅接收 arp 响应帧和需要路由的帧  
  1786.     CString Filter, Filter0, Filter1;  
  1787.     Filter0 = "(";  
  1788.     Filter1 = "(";  
  1789.     for (i = 0; i < IfCount; i++)  
  1790.     {  
  1791.         Filter0 += _T("(ether dst ") + MACntoa(IfInfo[i].MACAddr) + _T(")");  
  1792.         for (j = 0; j < IfInfo[i].ip.GetSize(); j++)  
  1793.         {  
  1794.             Filter1 += _T("(ip dst host ") + IPntoa(IfInfo[i].ip[j].IPAddr) + _T(")");  
  1795.             if (((j == (IfInfo[i].ip.GetSize() - 1))) && (i == (IfCount - 1)))  
  1796.             {  
  1797.                 Filter1 += ")";  
  1798.             }  
  1799.             else  
  1800.             {  
  1801.                 Filter1 += " or ";  
  1802.             }  
  1803.         }  
  1804.         if (i == (IfCount - 1))  
  1805.         {  
  1806.             Filter0 += ")";  
  1807.         }  
  1808.         else  
  1809.         {  
  1810.             Filter0 += " or ";  
  1811.         }  
  1812.     }  
  1813.     Filter = Filter0 + _T(" and ((arp and (ether[21]=0x2)) or (not") + Filter1 + _T("))");  
  1814.     sprintf_s(strbuf, "%s", Filter);  
  1815.     //TRACE1("filter:%s /n",strbuf);  
  1816.     for (i = 0; i < IfCount; i++)  
  1817.     {  
  1818.         if (pcap_compile(IfInfo[i].adhandle, &fcode, strbuf, 1,  
  1819.             IfInfo[i].ip[0].IPMask) < 0)  
  1820.         {  
  1821.             MessageBox(_T("过滤规则编译不成功,请检查书写的规则语法是否正确! "));  
  1822.             PostMessage(WM_QUIT, 0, 0);  
  1823.         }  
  1824.         if (pcap_setfilter(IfInfo[i].adhandle, &fcode) < 0)  
  1825.         {  
  1826.             MessageBox(_T("设置过滤器错误! "));  
  1827.             PostMessage(WM_QUIT, 0, 0);  
  1828.         }  
  1829.     }  
  1830.     // 不再需要该设备列表,释放之  
  1831.     pcap_freealldevs(alldevs);  
  1832.     TimerCount = 1;  
  1833.     // 开始捕获数据包  
  1834.     for (i = 0; i < IfCount; i++)  
  1835.     {  
  1836.         pthread = AfxBeginThread(Capture, &IfInfo[i],  
  1837.             THREAD_PRIORITY_NORMAL);  
  1838.         if (!pthread)  
  1839.         {  
  1840.             MessageBox(_T("创建数据包捕获线程失败! "));  
  1841.             PostMessage(WM_QUIT, 0, 0);  
  1842.         }  
  1843.     }  
  1844. }  
  1845.   
  1846.   
  1847. void CVCRouterDlg::OnBnClickedButton()  
  1848. {  
  1849.     // TODO:  在此添加控件通知处理程序代码  
  1850.     SendMessage(WM_CLOSE);  
  1851. }  
  1852.   
  1853.   
  1854. void CVCRouterDlg::OnAddRouterButton()  
  1855. {  
  1856.     // TODO:  在此添加控件通知处理程序代码  
  1857.     bool flag;  
  1858.     int i, j;  
  1859.     DWORD ipaddr;  
  1860.     RouteTable_t rt;  
  1861.     m_NextHop.GetAddress(ipaddr);  
  1862.     ipaddr = htonl(ipaddr);  
  1863.     // 检查合法性  
  1864.     flag = false;  
  1865.     for (i = 0; i < IfCount; i++)  
  1866.     {  
  1867.         for (j = 0; j < IfInfo[i].ip.GetSize(); j++)  
  1868.         {  
  1869.             if (((IfInfo[i].ip[j].IPAddr) & (IfInfo[i].ip[j].IPMask)) ==  
  1870.                 ((IfInfo[i].ip[j].IPMask) & ipaddr))  
  1871.             {  
  1872.                 rt.IfNo = i;  
  1873.                 // 记录子网掩码  
  1874.                 m_Mask.GetAddress(ipaddr);  
  1875.                 rt.Mask = htonl(ipaddr);  
  1876.                 // 记录目的 IP  
  1877.                 m_Destination.GetAddress(ipaddr);  
  1878.                 rt.DstIP = htonl(ipaddr);  
  1879.                 // 记录下一跳  
  1880.                 m_NextHop.GetAddress(ipaddr);  
  1881.                 rt.NextHop = htonl(ipaddr);  
  1882.                 // 把该条路由表项添加到路由表  
  1883.                 RouteTable.AddTail(rt);  
  1884.                 // 在路由表窗口中显示该路由表项  
  1885.                 m_RouteTable.InsertString(-1, IPntoa(rt.Mask) + " -- "  
  1886.                     + IPntoa(rt.DstIP) + " -- " + IPntoa(rt.NextHop));  
  1887.                 flag = true;  
  1888.             }  
  1889.         }  
  1890.     }  
  1891.     if (!flag)  
  1892.     {  
  1893.         MessageBox(_T("输入错误,请重新输入! "));  
  1894.     }  
  1895. }  
  1896.   
  1897.   
  1898. void CVCRouterDlg::OnDeleteRouterButton()  
  1899. {  
  1900.     // TODO:  在此添加控件通知处理程序代码  
  1901.     int i;  
  1902.     char str[100], ipaddr[20];  
  1903.     ULONG mask, destination, nexthop;  
  1904.     RouteTable_t rt;  
  1905.     POSITION pos, CurrentPos;  
  1906.     str[0] = NULL;  
  1907.     ipaddr[0] = NULL;  
  1908.     if ((i = m_RouteTable.GetCurSel()) == LB_ERR)  
  1909.     {  
  1910.         return;  
  1911.     }  
  1912.     m_RouteTable.GetText(i, (LPTSTR)str);  
  1913.     // 取得子网掩码选项  
  1914.     strncat_s(ipaddr, str, 15);  
  1915.     mask = inet_addr(ipaddr);  
  1916.     // 取得目的地址选项  
  1917.     ipaddr[0] = 0;  
  1918.     strncat_s(ipaddr, &str[19], 15);  
  1919.     destination = inet_addr(ipaddr);  
  1920.     // 取得下一跳选项  
  1921.     ipaddr[0] = 0;  
  1922.     strncat_s(ipaddr, &str[38], 15);  
  1923.     nexthop = inet_addr(ipaddr);  
  1924.     if (nexthop == 0)  
  1925.     {  
  1926.         MessageBox(_T("直接连接路由,不允许删除! "));  
  1927.         return;  
  1928.     }  
  1929.     // 把该路由表项从路由表窗口中删除  
  1930.     m_RouteTable.DeleteString(i);  
  1931.     // 路由表中没有需要处理的内容,则返回  
  1932.     if (RouteTable.IsEmpty())  
  1933.     {  
  1934.         return;  
  1935.     }  
  1936.     // 遍历路由表,把需要删除的路由表项从路由表中删除  
  1937.     pos = RouteTable.GetHeadPosition();  
  1938.     for (i = 0; i < RouteTable.GetCount(); i++)  
  1939.     {  
  1940.         CurrentPos = pos;  
  1941.         rt = RouteTable.GetNext(pos);  
  1942.         if ((rt.Mask == mask) && (rt.DstIP == destination) && (rt.NextHop ==  
  1943.             nexthop))  
  1944.         {  
  1945.             RouteTable.RemoveAt(CurrentPos);  
  1946.             return;  
  1947.         }  
  1948.     }  
  1949. }  
  1950.   
  1951. //????????????  
  1952. void CVCRouterDlg::OnDestroy()  
  1953. {  
  1954.     // TODO: Add your control notification handler code here  
  1955.     CDialog::OnDestroy();  
  1956.     // TODO: Add your message handler code here  
  1957.     SP.RemoveAll();  
  1958.     IP_MAC.RemoveAll();  
  1959.     RouteTable.RemoveAll();  
  1960.     for (int i = 0; i < IfCount; i++)  
  1961.     {  
  1962.         IfInfo[i].ip.RemoveAll();  
  1963.     }  
  1964. }  
  1965.   
  1966. void CVCRouterDlg::OnTimer(UINT nIDEvent)  
  1967. {  
  1968.     // TODO: Add your message handler code here and/or call default  
  1969.     SendPacket_t sPacket;  
  1970.     POSITION pos, CurrentPos;  
  1971.     IPFrame_t *IPf;  
  1972.     // 没有需要处理的内容  
  1973.     if (SP.IsEmpty())  
  1974.     {  
  1975.         return;  
  1976.     }  
  1977.     mMutex.Lock(INFINITE);  
  1978.     // 遍历转发缓存区  
  1979.     pos = SP.GetHeadPosition();  
  1980.     for (int i = 0; i < SP.GetCount(); i++)  
  1981.     {  
  1982.         CurrentPos = pos;  
  1983.         sPacket = SP.GetNext(pos);  
  1984.         if (sPacket.n_mTimer == nIDEvent)  
  1985.         {  
  1986.             IPf = (IPFrame_t *)sPacket.PktData;  
  1987.             // 日志输出信息  
  1988.             Logger.InsertString(-1, _T("IP 数据报在转发队列中等待 10 秒后还未能被转发"));  
  1989.             Logger.InsertString(-1, (_T(" 定时器中删除该 IP 数据报: ") +  
  1990.                 IPntoa(IPf->IPHeader.SrcIP) + "->"  
  1991.                 + IPntoa(IPf->IPHeader.DstIP) + " " +  
  1992.                 MACntoa(IPf->FrameHeader.SrcMAC)  
  1993.                 + _T("->xx:xx:xx:xx:xx:xx")));  
  1994.             KillTimer(sPacket.n_mTimer);  
  1995.             SP.RemoveAt(CurrentPos);  
  1996.         }  
  1997.     }  
  1998.     mMutex.Unlock();  
  1999.     CDialog::OnTimer(nIDEvent);  
  2000. }
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值