简单路由器设计与实现.docx
《简单路由器设计与实现.docx》由会员分享,可在线阅读,更多相关《简单路由器设计与实现.docx(54页珍藏版)》请在冰点文库上搜索。
简单路由器设计与实现
简单路由器设计与实现(选做)
1.实验目的
熟悉并掌握路由器的工作原理;熟悉Winpcap编程,掌握数据包捕获与发送的方法;在理解IP协议、ICMP协议与路由基本工作原理的基础上,完成一个(软件)路由器基本功能的设计与编程实现。
2.实验环境
Ø接入局域网的PC机;
Ø操作系统:
Windowsxp,Windows7等;
Ø推荐开发工具:
VisualStudio2010;
Ø推荐编程语言:
C++/VisualC++;
Ø函数库/开发包:
Winpcap。
3.实验容
(1)学习并掌握winpcap编程:
自行完成WinPcap教程中的容,从而掌握winpcap编程。
容包括但不限于:
a)获取设备列表;
b)打开一个适配器并抓包(分组);
c)解析分组;
d)发送分组;
学习容及源程序参见WinPcap官方教程:
.winpcap.org/docs/docs_412/html/group_wpcap_tut.html。
(2)利用winpcap开发包实现简单路由程序,该路由程序应该至少包括以下功能:
a)IP数据包捕获和转发;
b)ARP请求与解析;
c)重新计算IP数据包的头部校验和;
d)处理IP数据包的头部校验和;处理IP数据包的TTL值;
e)静态路由表维护。
在下图所示的完了过拓扑结构中,当所开发的路由器程序部署并运行在计算机C上时,它将(作为一个路由器)能够连通两个子网,正确地捕获、转发来自计算机A和计算机B的分组,使得两个子网中的主机能够互相访问
图5-1实验验证环境配置示意图
4.实验方式
每位同学独立上机编程实验,实验指导教师现场指导。
5.参考容
(1)WinPcap简介
Winpcap(windowspacketcapture)是windows平台下一个免费、公共的网络访问系统。
开发Winpcap项目的目的在于为win32应用程序提供访问网络底层的能力。
它用于windows系统下的直接的网络编程。
关于Winpcap的介绍请参阅
baike.baidu./link?
url=rQt7NLzLCFGDO8Fd2XoM3yMvpqRhA4NU6xjLdWtoS_JkMLVfgQ9mspXhMceA5RVYIl9CnA2w66uEPrSlUXKq3_。
Winpcap开发包可以在www.winpcap.org/上下载,Winpcap的技术文档可以从www.winpcap.org/docs/default.htm下载。
附录中给出了主要函数的说明文档。
(2)Winpcap主要函数及功能介绍
Winpcap部分主要函数及其功能介绍如下:
(1).intpcap_findalldevs_ex(char*source,structpcap_rmtauth*auth,pcap_if_t**alldevs,char*errbuf)
函数功能:
Createalistofnetworkdevicesthatcanbeopenedwith pcap_open().
参数说明:
source:
achar*bufferthatkeepsthe'sourcelocaltion',accordingtothenewWinPcapsyntax.Thissourcewillbeexaminedlookingforadapters(localorremote)orpcapfiles,Thestringsthatmustbeprependedtothe'source'inordertodefineifwewantlocal/remoteadaptersorfilesisdefinedinthenewSourceSpecificationSyntax.
auth:
apointertoapcap_rmtauthstructure.ThispointerkeepstheinformationrequiredtoauthenticatetheRPCAPconnectiontotheremotehost.Thisparameterisnotmeaningfulincaseofaquerytothelocalhost:
inthatcaseitcanbeNULL.
alldevs:
a'structpcap_if_t'pointer,whichwillbeproperlyallocatedinsidethisfunction.Whenthefunctionreturns,itissettopointtothefirstelementoftheinterfacelist;eachelementofthelistisoftype'structpcap_if_t'.
errbuf:
apointertoauser-allocatedbuffer(ofsizePCAP_ERRBUF_SIZE)thatwillcontaintheerrormessage(incasethereisone).
返回值:
'0'ifeverythingisfine,'-1'ifsomeerrorsoccurred.Thelistofthedevicesisreturnedinthe'alldevs'variable.Whenthefunctionreturnscorrectly,'alldevs'cannotbeNULL.Inotherwords,thisfunctionreturns'-1'alsoincasethesystemdoesnothaveanyinterfacetolist.
(2).voidpcap_freealldevs_ex(pcap_if_t*alldevsp)
函数功能:
Freeaninterfacelistreturnedbypcap_findalldevs().
(3).pcap_t*pcap_open(constchar*source,intsnaplen,intflags,intread_timeout,structpcap_rmtauth*auth,char*errbuf)
函数功能:
Openagenericsourceinordertocapture/send(WinPcaponly)traffic.
参数说明:
source:
zero-terminatedstringcontainingthesourcenametoopen.ThesourcenamehastoincludetheformatprefixaccordingtothenewSourceSpecificationSyntaxanditcannotbeNULL.OnonLinuxsystemswith2.2orlaterkernels,adeviceargumentof"any"canbeusedtocapturepacketsfromallinterfaces.Inordertomakesthesourcesyntaxeasier,pleaserememberthat:
theadaptersreturnedbythepcap_findalldevs_ex()canbeusedimmediatelybythepcap_open()incasetheuserwantstopassitsownsourcestringtothepcap_open(),thepcap_createsrcstr()helpsincreatingthecorrectsourceidentifier.
snaplen:
lengthofthepacketthathastoberetained.Foreachpacketreceivedbythefilter,onlythefirst'snaplen'bytesarestoredinthebufferandpassedtotheuserapplication.Forinstance,snaplenequalto100meansthatonlythefirst100bytesofeachpacketarestored.
flags:
keepsseveralflagsthatcanbeneededforcapturingpackets.Theallowedflagsaredefinedinthepcap_open()flags.
read_timeout:
readtimeoutinmilliseconds.Thereadtimeoutisusedtoarrangethatthereadnotnecessarilyreturnimmediatelywhenapacketisseen,butthatitwaitsforsomeamountoftimetoallowmorepacketstoarriveandtoreadmultiplepacketsfromtheOSkernelinoneoperation.Notallplatformssupportareadtimeout;onplatformsthatdon't,thereadtimeoutisignored.
auth:
apointertoa'structpcap_rmtauth'thatkeepstheinformationrequiredtoauthenticatetheuseronaremotemachine.Incasethisisnotaremotecapture,thispointercanbesettoNULL.
errbuf:
apointertoauser-allocatedbufferwhichwillcontaintheerrorincasethisfunctionfails.Thepcap_open()andfindalldevs()aretheonlytwofunctionswhichhavethisparameter,sincetheydonothave(yet)apointertoapcap_tstructure,whichreservesspacefortheerrorstring.Sincethesefunctionsdonothave(yet)apcap_tpointer(thepcap_tpointerisNULLincaseoferrors),theyneedanexplicit'errbuf'variable.'errbuf'mayalsobesettowarningtextwhenpcap_open_live()succeds;todetectthiscasethecallershouldstoreazero-lengthstringin'errbuf'beforecallingpcap_open_live()anddisplaythewarningtotheuserif'errbuf'isnolongerazero-lengthstring.
返回值:
Apointertoa'pcap_t'whichcanbeusedasaparametertothefollowingcalls(pcap_compile() andsoon)andthatspecifiesanopenedWinPcapsession.Incaseofproblems,itreturnsNULLandthe'errbuf'variablekeepstheerrormessage.
(4).intpcap_next_ex(pcap_t*p,structpcap_pkthdr**pkt_header,constu_char**pkt_data)
函数功能:
Readapacketfromaninterfaceorfromanofflinecapture.Thisfunctionisusedtoretrievethenextavailablepacket,bypassingthecallbackmethodtraditionallyprovidedbylibpcap.pcap_next_exfillsthepkt_headerandpkt_dataparameters(seepcap_handler())withthepointerstotheheaderandtothedataofthenextcapturedpacket.
返回值:
Thereturnvaluecanbe:
1ifthepackethasbeenreadwithoutproblems
0ifthetimeoutsetwithpcap_open_live()haselapsed.Inthiscasepkt_headerandpkt_datadon'tpointtoavalidpacket
-1ifanerroroccurred
-2ifEOFwasreachedreadingfromanofflinecapture
(5).intpcap_compile(pcap_t*p,structbpf_program*fp,char*str,intoptimize,bpf_u_int32netmask)
函数功能:
Compileapacketfilter,convertinganhighlevelfilteringexpression(seeFilteringexpressionsyntax)inaprogramthatcanbeinterpretedbythekernel-levelfilteringengine.
(6).intpcap_setfilter(pcap_t*p,structbpf_program*fp)
函数功能:
Associateafiltertoacapture.此函数是要和函数pcap_compile()配合使用。
(7).intpcap_sendpacket(pcap_t*p,u_char*buf,intsize)
函数功能:
Sendarawpacket.
6.实验步骤
6.1WinPcap开发包安装与配置
下载、安装WinPcap开发包,配置VisualStudio2010开发环境。
具体步骤请同学们参阅网上资料自行完成。
6.2用户界面设计
(1).首先打开vs2010,新建工程,选择MFCApplication,输入工程名,点击OK,
图5-2
点击next,选择Dialogbased,点击Next跳到最后一个页面选择...Dlg,点击finish。
图5-3
图5-4
到此为止工程新建完毕,运行会出现以下页面,下面就为这个对话框拖拽控件。
图5-5
首先将对话框上面的三个控件删除,并拖拽相应的控件得到如下效果:
图5-6
图5-7
其中对话框可在ResourceView打开,控件在Toolbox中可以找到,
图5-8
其中启动、退出、添加路由、删除路由为button控件,两个空白区为ListBox,日志、路由表、子网掩码、目的地址、下一跳步为StaticText,三个输入IP的控件为IPAddressControl,将控件拖拽到相应的位置并且在控件的属性框中修改控件的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_BUTTON
6.3代码实现
(1).事件响应函数及主流程
控件添加完成后为Button添加相应的单击事件并修改单击事件名称,对应关系如下:
启动
OnStartClickedButton()
退出
OnBnClickedButton()
添加路由
OnAddRouterButton()
删除路由
OnDeleteRouterButton()
VC程序首先执行程序初始化函数OnInitDialog(),在此函数中我们获取了MFC窗体指针。
当我们点击“启动”按钮时,程序会执行OnStartClickedButton()函数,此函数流程图如下图所示:
图5-9
当我们点击结束按钮时程序会执行OnBnClickedButton(),程序自动退出。
当程序退出时会触发ON_WM_DESTROY()消息,从而会执行OnDestroy()函数,并且程序在执行过程中每隔一段时间会执行OnTimer()函数。
(2).主要数据结构和函数声明
首先将程序所用变量以及函数复制到VCRouterDlg.cpp文件中:
#defineMAX_IF5//最大接口数目
#pragmapack
(1)
typedefstructFrameHeader_t{//帧首部
UCHARDesMAC[6];//目的地址
UCHARSrcMAC[6];//源地址
USHORTFrameType;//帧类型
}FrameHeader_t;
typedefstructARPFrame_t{//ARP帧
FrameHeader_tFrameHeader;//帧首部
WORDHardwareType;//硬件类型
WORDProtocolType;//协议类型
BYTEHLen;//硬件地址长度
BYTEPLen;//协议地址长度
WORDOperation;//操作值
UCHARSendHa[6];//源MAC地址
ULONGSendIP;//源IP地址
UCHARRecvHa[6];//目的MAC地址
ULONGRecvIP;//目的IP地址
}ARPFrame_t;
typedefstructIPHeader_t{//IP首部
BYTEVer_HLen;//版本+头部长度
BYTETOS;//服务类型
WORDTotalLen;//总长度
WORDID;//标识
WORDFlag_Segment;//标志+片偏移
BYTETTL;//生存时间
BYTEProtocol;//协议
WORDChecksum;//头部校验和
ULONGSrcIP;//源IP地址
ULONGDstIP;//目的IP地址
}IPHeader_t;
typedefstructICMPHeader_t{//ICMP首部
BYTEType;//类型
BYTECode;//代码
WORDChecksum;//校验和
WORDId;//标识
WORDSequence;//序列号
}ICMPHeader_t;
typedefstructIPFrame_t{//IP帧
FrameHeader_tFrameHeader;//帧首部
IPHeader_tIPHeader;//IP首部
}IPFrame_t;
typedefstructip_t{//网络地址
ULONGIPAddr;//IP地址
ULONGIPMask;//子网掩码
}ip_t;
typedefstructIfInfo_t{//接口信息
CStringDeviceName;//设备名
CStringDescription;//设备描述
UCHARMACAddr[6];//MAC地址
CArrayip;//IP地址列表
pcap_t*adhandle;//pcap句柄
}IfInfo_t;
typedefstructSendPacket_t{//发送数据包结构
intlen;//长度
BYTEPktData[2000];//数据缓存
ULONGTargetIP;//目的IP地址
UINT_PTRn_mTimer;//定时器
UINTIfNo;//接口序号
}SendPacket_t;
typedefstructRouteTable_t{//路由表结构
ULONGMask;//子网掩码
ULONGDstIP;//目的地址
ULONGNextHop;//下一跳步
UINTIfNo;//接口序号
}RouteTable_t;
typedefstructIP_MAC_t{//IP-MAC地址映射结构
ULONGIPAddr;//IP地址
UCHARMACAddr[6];//MAC地址
}IP_MAC_t;
//全局变量
/*************************************************************************/
IfInfo_tIfInfo[M