簡單路由器設計與實現_第1頁
簡單路由器設計與實現_第2頁
簡單路由器設計與實現_第3頁
簡單路由器設計與實現_第4頁
簡單路由器設計與實現_第5頁
已閱讀5頁,還剩33頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、簡單路由器設計與實現(選做)1.實驗目的熟悉并掌握路由器的工作原理;熟悉Winpcap編程,掌握數據包捕獲與發送的方法;在理解IP協議、ICMP協議與路由基本工作原理的基礎上,完成一個(軟件)路由器基本功能的設計與編程實現。2.實驗環境 接入局域網的PC機; 操作系統:Windows xp, Windows 7等; 推薦開發工具:Visual Studio 2010; 推薦編程語言:C+/ Visual C+; 函數庫/開發包:Winpcap。3.實驗內容(1) 學習并掌握winpcap編程:自行完成WinPcap教程中的內容,從而掌握winpcap編程。內容包括但不限于:a) 獲取設備列表;

2、b) 打開一個適配器并抓包(分組);c) 解析分組;d) 發送分組;學習內容及源程序參見WinPcap官方教程:/docs/docs_412/html/group_wpcap_tut.html。(2) 利用winpcap開發包實現簡單路由程序,該路由程序應該至少包括以下功能:a) IP數據包捕獲和轉發;b) ARP請求與解析;c) 重新計算IP數據包的頭部校驗和;d) 處理IP數據包的頭部校驗和;處理IP數據包的TTL值;e) 靜態路由表維護。在下圖所示的完了過拓撲結構中,當所開發的路由器程序部署并運行在計算機C上時,它將(作為一個路由器)能夠連通兩個

3、子網,正確地捕獲、轉發來自計算機A和計算機B的分組,使得兩個子網中的主機能夠互相訪問圖5-1 實驗驗證環境配置示意圖4.實驗方式每位同學獨立上機編程實驗,實驗指導教師現場指導。5.參考內容(1) WinPcap簡介Winpcap (windows packet capture)是windows平臺下一個免費、公共的網絡訪問系統。開發Winpcap項目的目的在于為win32應用程序提供訪問網絡底層的能力。它用于windows系統下的直接的網絡編程。關于Winpcap的介紹請參閱Winpcap開發包可以在/上下載,Winpcap的技術文檔可以從http:/

4、/docs/default.htm下載。附錄中給出了主要函數的說明文檔。(2) Winpcap主要函數及功能介紹Winpcap部分主要函數及其功能介紹如下:(1).int pcap_findalldevs_ex(char * source, struct pcap_rmtauth * auth, pcap_if_t * alldevs, char * errbuf)函數功能:Create a list of network devices that can be opened withpcap_open().參數說明:source:a char* buffer t

5、hat keeps the source localtion, according to the new WinPcap syntax. This source will be examined looking for adapters (local or remote) or pcap files,The strings that must be prepended to the source in order to define if we want local/remote adapters or files is defined in the new Source Specificat

6、ion Syntax .auth:a pointer to a pcap_rmtauth structure. This pointer keeps the information required to authenticate the RPCAP connection to the remote host. This parameter is not meaningful in case of a query to the local host: in that case it can be NULL.alldevs:a struct pcap_if_t pointer, which wi

7、ll be properly allocated inside this function. When the function returns, it is set to point to the first element of the interface list; each element of the list is of type struct pcap_if_t.errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE) that will contain the error message (i

8、n case there is one).返回值:0 if everything is fine, -1 if some errors occurred. The list of the devices is returned in the alldevs variable. When the function returns correctly, alldevs cannot be NULL. In other words, this function returns -1 also in case the system does not have any interface to list

9、.(2).void pcap_freealldevs_ex(pcap_if_t * alldevsp)函數功能:Free an interface list returned by pcap_findalldevs().(3).pcap_t* pcap_open(const char * source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth * auth, char * errbuf)函數功能:Open a generic source in order to capture / send (WinPcap

10、only) traffic.參數說明:source:zero-terminated string containing the source name to open. The source name has to include the format prefix according to the new Source Specification Syntax and it cannot be NULL.On on Linux systems with 2.2 or later kernels, a device argument of any can be used to capture

11、packets from all interfaces. In order to makes the source syntax easier, please remember that:the adapters returned by the pcap_findalldevs_ex() can be used immediately by the pcap_open()in case the user wants to pass its own source string to the pcap_open(), the pcap_createsrcstr() helps in creatin

12、g the correct source identifier.snaplen:length of the packet that has to be retained. For each packet received by the filter, only the first snaplen bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packe

13、t are stored.flags:keeps several flags that can be needed for capturing packets. The allowed flags are defined in the pcap_open() flags .read_timeout:read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it

14、waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that dont, the read timeout is ignored.auth:a pointer to a struct pcap_rmtauth that keeps the information required to

15、 authenticate the user on a remote machine. In case this is not a remote capture, this pointer can be set to NULL.errbuf:a pointer to a user-allocated buffer which will contain the error in case this function fails. The pcap_open() and findalldevs() are the only two functions which have this paramet

16、er, since they do not have (yet) a pointer to a pcap_t structure, which reserves space for the error string. Since these functions do not have (yet) a pcap_t pointer (the pcap_t pointer is NULL in case of errors), they need an explicit errbuf variable. errbuf may also be set to warning text when pca

17、p_open_live() succeds; to detect this case the caller should store a zero-length string in errbuf before calling pcap_open_live() and display the warning to the user if errbuf is no longer a zero-length string.返回值: A pointer to a pcap_t which can be used as a parameter to the following calls (pcap_c

18、ompile()and so on) and that specifies an opened WinPcap session. In case of problems, it returns NULL and the errbuf variable keeps the error message.(4). int pcap_next_ex(pcap_t * p, struct pcap_pkthdr * pkt_header, const u_char * pkt_data)函數功能:Read a packet from an interface or from an offline cap

19、ture.This function is used to retrieve the next available packet, bypassing the callback method traditionally provided by libpcap. pcap_next_ex fills the pkt_header and pkt_data parameters (see pcap_handler() with the pointers to the header and to the data of the next captured packet.返回值:The return

20、value can be:1 if the packet has been read without problems0 if the timeout set with pcap_open_live() has elapsed. In this case pkt_header and pkt_data dont point to a valid packet-1 if an error occurred-2 if EOF was reached reading from an offline capture(5). int pcap_compile(pcap_t * p, struct bpf

21、_program * fp, char * str, int optimize, bpf_u_int32 netmask)函數功能:Compile a packet filter, converting an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine.(6). int pcap_setfilter(pcap_t * p, struct bpf_program

22、* fp)函數功能:Associate a filter to a capture. 此函數是要和函數pcap_compile()配合使用。(7). int pcap_sendpacket(pcap_t * p, u_char * buf, int size)函數功能: Send a raw packet.6.實驗步驟6.1 WinPcap開發包安裝與配置下載、安裝WinPcap開發包,配置VisualStudio 2010開發環境。具體步驟請同學們參閱網上資料自行完成。6.2 用戶界面設計(1).首先打開vs2010,新建工程,選擇MFC Application,輸入工程名,點擊OK,圖5-

23、2點擊next,選擇Dialog based,點擊Next跳到最后一個頁面選擇.Dlg,點擊finish。圖5-3圖5-4到此為止工程新建完畢,運行會出現以下頁面,下面就為這個對話框拖拽控件。圖5-5首先將對話框上面的三個控件刪除,并拖拽相應的控件得到如下效果:圖5-6圖5-7其中對話框可在Resource View打開,控件在Toolbox中可以找到,圖5-8其中啟動、退出、添加路由、刪除路由為button控件,兩個空白區為List Box,日志、路由表、子網掩碼、目的地址、下一跳步為Static Text,三個輸入IP的控件為IP Address Control,將控件拖拽到相應的位置并且

24、在控件的屬性框中修改控件的Caption以及ID。啟動ONSTART_BUTTON退出ONSTOP_BUTTON日志IDC_STATIC第一個空白區LOGGER_LIST路由表IDC_STATIC第二個空白區ROUTER_LIST子網掩碼IDC_STATIC子網掩碼對應的IP輸入區IDC_NETMASK目的地址IDC_STATIC目的地址對應的IP輸入區IDC_IPADDRESS下一跳步IDC_STATIC下一跳步對應的IP輸入區IDC_NEXTHOP添加路由ADD_ROUTER_BUTTON刪除路由DELETE_ROUTER_BUTTON6.3 代碼實現(1). 事件響應函數及主流程控件添加

25、完成后為Button添加相應的單擊事件并修改單擊事件名稱,對應關系如下:啟動OnStartClickedButton()退出OnBnClickedButton()添加路由OnAddRouterButton()刪除路由OnDeleteRouterButton()VC程序首先執行程序初始化函數OnInitDialog(),在此函數中我們獲取了MFC窗體指針。當我們點擊“啟動”按鈕時,程序會執行OnStartClickedButton()函數,此函數流程圖如下圖所示:圖5-9當我們點擊結束按鈕時程序會執行OnBnClickedButton(),程序自動退出。當程序退出時會觸發ON_WM_DESTRO

26、Y()消息,從而會執行OnDestroy()函數,并且程序在執行過程中每隔一段時間會執行OnTimer()函數。(2). 主要數據結構和函數聲明首先將程序所用變量以及函數復制到VCRouterDlg.cpp文件中:#defineMAX_IF5 / 最大接口數目#pragma pack(1)typedef struct FrameHeader_t / 幀首部 UCHARDesMAC6; / 目的地址 UCHARSrcMAC6; / 源地址 USHORTFrameType; / 幀類型 FrameHeader_t;typedef struct ARPFrame_t / ARP幀FrameHeade

27、r_tFrameHeader; / 幀首部 WORDHardwareType; / 硬件類型WORDProtocolType; / 協議類型BYTEHLen; / 硬件地址長度BYTEPLen; / 協議地址長度WORDOperation; / 操作值UCHARSendHa6; / 源MAC地址ULONGSendIP; / 源IP地址UCHARRecvHa6; / 目的MAC地址ULONGRecvIP; / 目的IP地址 ARPFrame_t;typedef struct IPHeader_t / IP首部BYTEVer_HLen; / 版本+頭部長度BYTETOS; / 服務類型WORDTo

28、talLen; / 總長度WORDID; / 標識WORDFlag_Segment; / 標志+片偏移BYTETTL; / 生存時間BYTEProtocol; / 協議WORDChecksum; / 頭部校驗和ULONGSrcIP; / 源IP地址ULONGDstIP; / 目的IP地址 IPHeader_t;typedef struct ICMPHeader_t / ICMP首部BYTE Type; / 類型BYTE Code; / 代碼WORD Checksum; / 校驗和WORD Id; / 標識WORD Sequence; / 序列號 ICMPHeader_t;typedef str

29、uct IPFrame_t / IP幀FrameHeader_tFrameHeader; / 幀首部IPHeader_tIPHeader; / IP首部 IPFrame_t;typedef struct ip_t / 網絡地址ULONGIPAddr; / IP地址ULONGIPMask; / 子網掩碼 ip_t;typedef struct IfInfo_t / 接口信息CStringDeviceName; / 設備名CStringDescription; / 設備描述UCHARMACAddr6; / MAC地址CArray ip; / IP地址列表pcap_t*adhandle; / pca

30、p句柄 IfInfo_t;typedef struct SendPacket_t / 發送數據包結構intlen; / 長度BYTEPktData2000;/ 數據緩存ULONGTargetIP; / 目的IP地址UINT_PTRn_mTimer; / 定時器UINTIfNo; / 接口序號 SendPacket_t;typedef struct RouteTable_t / 路由表結構ULONGMask; / 子網掩碼ULONGDstIP; / 目的地址ULONGNextHop; / 下一跳步UINTIfNo; / 接口序號 RouteTable_t;typedef struct IP_MA

31、C_t / IP-MAC地址映射結構ULONGIPAddr; / IP地址UCHARMACAddr6; / MAC地址 IP_MAC_t;/ 全局變量/*/IfInfo_tIfInfoMAX_IF; / 接口信息數組intIfCount; / 接口個數UINT_PTR TimerCount; / 定時器個數CList SP; / 發送數據包緩存隊列CList IP_MAC; / IP-MAC地址映射列表CList RouteTable; / 路由表CMyRouterDlg *pDlg ; / 對話框指針CMutex mMutex(0,0,0); / 互斥/*/ 全局函數/*/ IP地址轉換CS

32、tring IPntoa(ULONG nIPAddr);/ MAC地址轉換CString MACntoa(UCHAR *nMACAddr);/ MAC地址比較bool cmpMAC(UCHAR *MAC1, UCHAR *MAC2);/ MAC地址復制void cpyMAC(UCHAR *MAC1, UCHAR *MAC2);/ MAC地址設置void setMAC(UCHAR *MAC, UCHAR ch);/ IP地址查詢bool IPLookup(ULONG ipaddr, UCHAR *p);/ 數據包捕獲線程UINT Capture(PVOID pParam);/ 獲取本地接口MAC

33、地址線程UINT CaptureLocalARP(PVOID pParam);/ 發送ARP請求void ARPRequest(pcap_t *adhandle, UCHAR *srcMAC, ULONG srcIP, ULONG targetIP);/ 查詢路由表DWORD RouteLookup(UINT &ifNO, DWORD desIP, CList *routeTable);/ 處理ARP數據包void ARPPacketProc(struct pcap_pkthdr *header, const u_char *pkt_data);/ 處理IP數據包void IPPacketPr

34、oc(IfInfo_t *pIfInfo, struct pcap_pkthdr *header, const u_char *pkt_data);/ 處理ICMP數據包void ICMPPacketProc(IfInfo_t *pIfInfo, BYTE type, BYTE code, const u_char *pkt_data);/ 檢查IP數據包頭部校驗和是否正確int IsChecksumRight(char * buffer);/ 計算校驗和unsigned short ChecksumCompute(unsigned short *buffer, int size);(3).

35、函數代碼實現/ 獲取本地接口MAC地址線程UINT CaptureLocalARP(PVOID pParam)intres;struct pcap_pkthdr*header;const u_char*pkt_data;IfInfo_t*pIfInfo;ARPFrame_t*ARPFrame;CStringDisplayStr;pIfInfo = (IfInfo_t *)pParam;while (true)Sleep(50);res = pcap_next_ex( pIfInfo-adhandle , &header, &pkt_data);/ 超時 if (res = 0) continu

36、e; if (res 0)ARPFrame = (ARPFrame_t *) (pkt_data);/ 得到本接口的MAC地址if (ARPFrame-FrameHeader.FrameType = htons(0x0806) & (ARPFrame-Operation = htons(0x0002) & (ARPFrame-SendIP = pIfInfo-ip0.IPAddr) cpyMAC(pIfInfo-MACAddr, ARPFrame-SendHa);return 0;void setMAC(UCHAR *MAC, UCHAR ch)for (int i=0; i6; i+) MA

37、Ci = ch;return;/ 發送ARP請求void ARPRequest(pcap_t *adhandle, UCHAR *srcMAC, ULONG srcIP, ULONG targetIP)ARPFrame_tARPFrame;inti;for (i=0; i6; i+)ARPFrame.FrameHeader.DesMACi = 255;ARPFrame.FrameHeader.SrcMACi = srcMACi;ARPFrame.SendHai = srcMACi;ARPFrame.RecvHai = 0;ARPFrame.FrameHeader.FrameType = hto

38、ns(0x0806);ARPFrame.HardwareType = htons(0x0001);ARPFrame.ProtocolType = htons(0x0800);ARPFrame.HLen = 6;ARPFrame.PLen = 4;ARPFrame.Operation = htons(0x0001);ARPFrame.SendIP = srcIP;ARPFrame.RecvIP = targetIP; pcap_sendpacket(adhandle, (u_char *) &ARPFrame, sizeof(ARPFrame_t);void cpyMAC(UCHAR *MAC1

39、, UCHAR *MAC2)for (int i=0; i6; i+) MAC1i=MAC2i;/ 比較兩個MAC地址是否相同bool cmpMAC(UCHAR *MAC1, UCHAR *MAC2)for (int i=0; iadhandle, &header, &pkt_data); if (res = 1)FrameHeader_t*fh;fh = (FrameHeader_t *) pkt_data;switch (ntohs(fh-FrameType)case 0x0806:ARPFrame_t *ARPf;ARPf = (ARPFrame_t *)pkt_data;/TRACE1

40、(收到ARP包 源IP為:%dn, ARPf-SendIP);/ ARP包,轉到ARP包處理函數ARPPacketProc(header, pkt_data);break;case 0x0800:IPFrame_t *IPf;IPf = (IPFrame_t*) pkt_data;/TRACE1(收到IP包 源IP為:%dn,IPf-IPHeader.SrcIP );/ IP包,轉到IP包處理函數IPPacketProc(pIfInfo, header, pkt_data);break;default: break;else if (res = 0)/ 超時continue;elseAfxMe

41、ssageBox(pcap_next_ex函數出錯!);return 0;/ 處理ARP數據包void ARPPacketProc(struct pcap_pkthdr *header, const u_char *pkt_data)boolflag;ARPFrame_tARPf;IPFrame_t*IPf;SendPacket_tsPacket;POSITIONpos, CurrentPos;IP_MAC_tip_mac;UCHARmacAddr6;ARPf = *(ARPFrame_t *)pkt_data;if (ARPf.Operation = ntohs(0x0002)pDlg-Lo

42、gger.InsertString(-1, 收到ARP響應包);pDlg-Logger.InsertString(-1, ( ARP +(IPntoa(ARPf.SendIP)+ - +MACntoa(ARPf.SendHa);/ IPMAC地址映射表中已經存在該對應關系if (IPLookup(ARPf.SendIP, macAddr) pDlg-Logger.InsertString(-1, 該對應關系已經存在于IPMAC地址映射表中);return;elseip_mac.IPAddr = ARPf.SendIP;memcpy(ip_mac.MACAddr, ARPf.SendHa, 6)

43、;/ 將IP-MAC映射關系存入表中IP_MAC.AddHead(ip_mac);/ 日志輸出信息pDlg-Logger.InsertString(-1, 將該對應關系存入IPMAC地址映射表中);mMutex.Lock(INFINITE);do/ 查看是否能轉發緩存中的IP數據報flag = false;/ 沒有需要處理的內容if (SP.IsEmpty() break;/ 遍歷轉發緩存區pos = SP.GetHeadPosition();for (int i=0; i FrameHeader.DesMAC, ARPf.SendHa);for(int t=0; tFrameHeader.S

44、rcMACt = IfInfosPacket.IfNo.MACAddrt;/ 發送IP數據包pcap_sendpacket(IfInfosPacket.IfNo.adhandle, (u_char *) sPacket.PktData, sPacket.len);SP.RemoveAt(CurrentPos);/ 日志輸出信息pDlg-Logger.InsertString(-1, 轉發緩存區中目的地址是該MAC地址的IP數據包);pDlg-Logger.InsertString(-1, ( 發送IP數據包:+IPntoa(IPf-IPHeader.SrcIP) + - + IPntoa(IP

45、f-IPHeader.DstIP) + + MACntoa(IPf-FrameHeader.SrcMAC )+-+MACntoa(IPf-FrameHeader.DesMAC);flag = true;break; while(flag);mMutex.Unlock();/ 查詢IP-MAC映射表bool IPLookup(ULONG ipaddr, UCHAR *p)IP_MAC_tip_mac;POSITIONpos;if (IP_MAC.IsEmpty() return false;pos = IP_MAC.GetHeadPosition(); for (int i = 0; iIP_MAC.GetCount(); i+

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論