详细设计说明书示例.docx
- 文档编号:27802220
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:99
- 大小:144.90KB
详细设计说明书示例.docx
《详细设计说明书示例.docx》由会员分享,可在线阅读,更多相关《详细设计说明书示例.docx(99页珍藏版)》请在冰豆网上搜索。
详细设计说明书示例
1.引言
1.1编写目的
本说明书提供了freeswan各个模块部件的说明,以供编码人员具体实现及今后的维护工作。
2.总体设计
2.1设计原则
在确定目标系统的过程中,主要遵循了以下几个原则:
◆目标系统基本上完整地实现IPSec协议族,完全支持VPN的要求;
◆目标系统的服务器端一定要建立在具有自主版权的内核操作系统之上;
◆目标系统的客户端使用方便、界面友好、配置和管理简单灵活。
2.2软件结构
该软件由如下几个模块组成:
◆KLIPS模块――实现对进入或外出IP包的安全处理,如:
加密、认证等(运行在内核空间)
◆Pluto模块――实现IKE协议,完成安全联盟的协商(运行在用户空间)
◆PF_KEY模块――实现pfkey2协议,完成上述两个模块间关于SA的通信
3.程序描述
3.1源代码文件组成
本程序由两大模块组成,一部分是klips,它运行在操作系统内核空间,主要负责安全联盟和密钥的管理工作,以及对数据报的加密、解密的处理工作;一部分是pluto,它是一个运行在用户空间的守护进程,主要负责安全联盟的协商工作。
下面分别是它们的文件组成:
源文件目录
|―――freeswan
|――klips
|――libdes
|――pluto
|――utils
3.2KLIPS(内核IPsec)详细设计
--―――klipsipsec的核心实现模块
|――net
|――ipsec
|――ipsec_init.c登记模块,并初始化
|――ipsec_tunnel.数据包的处理并发送模块
|――ipsec_rcv.c数据包接收并处理模块
|――ipsec_xform.c管理SA的模块
|――ipsec_sha1.csha1实现模块,由sha1.c改编
|――ipsec_md5c.cmd5.c实现模块
|――ipcomp.c
|――radij.c路由表的radix数的实现模块
|――ipsec_radij.c对上个文件的改编
|――pfkey_v2.c实现PF_KEY2协议的模块
|――pfkey_v2_parser.c对上个文件的改编
|――sysctl_net_ipsec.c
|――utils
|――eroute.c用户操作eroute表的模块
|――spi.c用户操作SA库的模块
|――spigrp.c同上
|――tncfg.c用户操作虚接口的模块
|――klipsdebug.c
3.2.1登记及初始化模块
3.2.1.1概要说明
3.2.1.1.1功能
向内核系统登记几个proc文件,以便于向内核空间中查询安全联盟和eoute表,以及虚接口的状况;
初始化SA数据库(tdb链);
初始化SPDB数据库(eroute表);
初始化pf_key(PF_KEY套接口);
3.2.1.1.2模块所涉及的文件
ipsec_init.c:
intipsec_init(void)
ipsec_xform.c:
intipsec_tdbinit(void)
ipsec_radij.c:
intipsec_radijinit(void)
pfkey_v2.c:
intpfkey_init(void)
3.2.1.2变量说明
3.2.1.2.1proc文件结构
将下列结构登记到内核系统中,则内核就可以通过proc文件系统向应用程序提供一个安全的界面来存取如SA、eroute表等资料。
structproc_dir_entryipsec_eroute;
structproc_dir_entryipsec_spi;
structproc_dir_entryipsec_spigrp;
structproc_dir_entryipsec_tncfg;
structproc_dir_entryipsec_spinew;
structproc_dir_entryipsec_klipsdebug;
3.2.1.2.2notifier_block结构
structnotifier_block结构是在include/linux/notifier.h里面的:
structnotifier_block
{
int(*notifier_call)(structnotifier_block*self,unsignedlong,void*);
structnotifier_block*next;
intpriority;
};
而register_netdevice_notifier函数在net/core/dev.c里面,是这样的:
intregister_netdevice_notifier(structnotifier_block*nb)
{
returnnotifier_chain_register(&netdev_chain,nb);
}
而notifier_chain_register函数在include/linux/notifier.h里面,是这样的:
extern__inline__intnotifier_chain_register(
structnotifier_block**list,structnotifier_block*n)
{
while(*list)
{
if(n->priority>(*list)->priority)
break;
list=&((*list)->next);
}
n->next=*list;
*list=n;
return0;
}
显然就是根据每个block的优先级把这个block排列在一个block的链表里面,在notifier_chain_register函数里面我们可以发现这个链表是netdev_chain。
实际上这个链表的作用就是在每个interface打开,关闭状态改变或者外界调用相应的ioctl的时候通知这个链表上面的所有相关的设备,而每一个协议都调用register_netdevice_notifier注册了一个netdev_notifier的结构体,这样就可以在interface改变的时候得到通知了(通过调用每个notifier_call函数)。
3.2.1.2.3inet_protocol结构
structinet_protocolah_protocol=
{
ipsec_rcv,/*AHhandler,定义此协议处理函数*/
NULL,/*TUNNELerrorcontrol,错误处理函数*/
0,/*next*/
IPPROTO_AH,/*protocolID*/
0,/*copy*/
NULL,/*data*/
"AH"/*name*/
};
ipsec_rcv函数是用来接收数据的callback函数,第二个是错误处理函数,其它的copy是用来协议共享的,这个以后再说,data当然就是这个结构体的私有数据了。
structinet_protocolesp_protocol同上;
inet_add_protocol函数在net/ipv4/protocol.c里实现:
voidinet_add_protocol(structinet_protocol*prot)
{
unsignedcharhash;
structinet_protocol*p2;
hash=prot->protocol&(MAX_INET_PROTOS-1);
prot->next=inet_protos[hash];
inet_protos[hash]=prot;
prot->copy=0;
p2=(structinet_protocol*)prot->next;
while(p2!
=NULL)
{
if(p2->protocol==prot->protocol)
{
prot->copy=1;
break;
}
p2=(structinet_protocol*)p2->next;
}
}
这个函数是生成了一个hash表,然后每个hash表项都是一个链表头,然后通过这个hash表加链表的方式访问每个协议结构体。
3.2.1.3函数说明
登记及初始化模块包括以下一些函数:
init_modules(),ipsec_init(),cleanup_module(),ipsec_cleanup(),
ipsec_eroute_get_info(),ipsec_spi_get_info(),ipsec_spigrp_get_info(),
ipsec_tncfg_get_info(),ipsec_version_get_info(),ipsec_spi_get_new()
3.2.1.3.1intinit_module(void)
目的:
装载ipsec时进行登记及初始化工作。
参数:
无
返回值:
0――初始化成功,非0值――初始化未成功
算法描述:
调用ipsec_init()。
3.2.1.3.2intcleanup_module(void)
目的:
卸载ipsec进行清除工作。
参数:
无
返回值:
0――初始化成功,非0值――初始化未成功
算法描述:
调用ipsec_cleanup()。
3.2.1.3.3intipsec_int(void)
目的:
装载ipsec时进行登记及初始化工作。
。
参数:
无
返回值:
0――初始化成功,非0值――初始化未成功
算法描述:
1.将定义好的几个proc_dir_entry结构注册到系统中,如:
proc_register(proc_net,&ipsec_eroute);/*PROC_FS_21*/或
proc_register_dynamic(&proc_net,&ipsec_eroute);或
proc_net_create(“ipsec_eroute”,0,ipsec_eroute_get_info);
proc_register为系统调用,在fs/proc/root.c中实现,主要就是在proc_net对应的目录下面生成每个协议的子目录。
用户可以通过访问/proc/net目录下面的相应目录得到相关的资料。
2.调用ipsec_tdbinit()函数初始化SA数据库,此函数在ipsec_tdb.c文件中实现;
3.调用ipsec_radijinit()函数初始化SPD数据库,此函数在ipsec_radij.c文件中实现;
4.调用pfkey_init()函数初始化PFKEY,此函数在pfkey_v2.c文件中实现;
5.调用register_netdevice_notifier(&ipsec_dev_notifier)函数向系统中注册已定义的ipsec_dev_notifier结构,register_netdevice_ntifier()为系统调用;
6.调用inet_add_protocol(&esp_protocol)和inet_add_protocol(&ah_protocol)函数向系统中注册ESP协议和AH协议,inet_add_protocol()为系统调用;
7.调用ipsec_tunnel_init_devices()函数,登记并初始化ipsec虚接口,此函数定义在ipsec_tunnel.c文件中。
3.2.1.3.4intipsec_cleanup(void)
目的:
卸载ipsec进行清除工作。
参数:
无
返回值:
0――清除成功,非0值――清除未成功
算法描述:
1.调用ipsec_tunnel_cleanup_device(void)函数,清除向系统登记的ipsec虚接口,此函数在ipsec_xform.c中实现;
2.调用inet_del_protocol(&ah_protocol)和inet_del_protocol(&esp_protocol)清除掉在系统中注册的ESP协议和AH协议;
3.调用系统调用unregister_netdevice_notifier(&ipsec_dev_notifier)清除掉系统中注册的ipsec_dev_notifier;
4.调用ipsec_tdbcleanup(0)清除系统中的SA数据库,此函数在ipsec_tdb.c中文件实现;
5.调用ipsec_radijcleanup()清除系统中的SPD数据库,此函数在ipsec_radij.c文件中实现;
6.调用pfkey_cleanup()做pfkey清除工作;
7.调用系统调用proc_net_unregister()清除freeswan在系统中登记的各个proc文件。
3.2.2虚接口模块
3.2.2.1概要说明
3.2.2.1.1功能
为了在不改变现有的操作系统的网络协议栈的状况下,更好地将IPsec嵌入,本程序采用了虚接口的概念。
实现中,将创建4个ipsec虚接口,可以将虚接口绑定在物理接口上。
对于从tcp/udp协议层传下来的数据,将首先查询eroute表,根据eroute表项决定将数据包发往哪一个接口,物理接口与虚接口将被视为一致的。
此时,如果数据包发往虚接口,则调用函数进行处理。
(该程序类似于网卡驱动程序的编写)
3.2.2.1.2构成文件
ipsec_tunnel.c
3.2.2.2变量说明
3.2.2.2.1device结构
虚接口定义为structdevice结构,如:
staticstructdevicedev_ipsec0=
{
"ipsec0\0",/*name*/
0,/*recvmemoryend*/
0,/*recvmemorystart*/
0,/*memoryend*/
0,/*memorystart*/
0x0,/*baseI/Oaddress*/
0,/*IRQ*/
0,0,0,/*flags*/
NULL,/*nextdevice*/
ipsec_tunnel_probe/*setup*/
};
3.2.2.2.2ipsecpriv结构
structipsecpriv
{
structsk_buff_headsendq;
structdevice*dev;
structwait_queue*wait_queue;
charlocked;
int(*hard_start_xmit)(structsk_buff*skb,structdevice*dev);
int(*hard_header)(structsk_buff*skb,
structdevice*dev,
unsignedshorttype,
void*daddr,
void*saddr,
unsignedlen);
#ifdefNET_21
int(*rebuild_header)(structsk_buff*skb);
#else/*NET_21*/
int(*rebuild_header)(void*buff,structdevice*dev,
unsignedlongraddr,structsk_buff*skb);
#endif/*NET_21*/
int(*set_mac_address)(structdevice*dev,void*addr);
#ifndefNET_21
void(*header_cache_bind)(structhh_cache**hhp,structdevice*dev,
unsignedshorthtype,__u32daddr);
#endif/*!
NET_21*/
void(*header_cache_update)(structhh_cache*hh,structdevice*dev,unsignedchar*haddr);
structenet_statistics*(*get_stats)(structdevice*dev);
structenet_statisticsmystats;
intmtu;/*WhatisthedesiredMTU?
*/
};
3.2.2.3函数说明
3.2.2.3.1intipsec_tunnel_init_devices(void)
目的:
登记ipsec虚接口。
参数:
无
返回值:
0――登记成功,非0值――登记未成功
算法描述:
调用系统调用register_netdev(&dev_ipsec0~3),向系统登记4个ipsec虚接口。
3.2.2.3.2intipsec_tunnel_init(structdevice*dev)
目的:
初始化ipsec虚接口,完成device中变量的初始化和系统资源的申请。
参数:
返回值:
0――清除成功,非0值――清除未成功
算法描述:
1.填充device结构中的几个函数,如:
a) dev->open=ipsec_tunnel_open;
b) dev->stop=ipsec_tunnel_stop;
c) dev->hard_start_xmit=ipsec_tunnel_start_xmit;
d) dev->get_stats=ipsec_tunnel_get_stats;
2.给dev配空间,dev->priv=kmalloc(sizeof(structipsecpriv),GFP_KERNEL);
3.初始化dev结构:
skb_queue_head_init(&dev->buffs[i]);
4.填充dev结构的其它值,如:
dev->set_mac_address=NULL等等。
3.2.2.3.3intipsec_tunnel_attach(structdevice*tndev,structipsecpriv*prv,structdevice*dev)
目的:
将某个虚接口绑定到指定的物理接口上。
参数:
返回值:
0――绑定成功,非0值――绑定未成功
算法描述:
3.2.2.3.4intipsec_open(structdevice*dev)
目的:
参数:
要open的device
返回值:
0――open成功,非0值――open未成功
算法描述:
此方法在网络设备驱动程序里是网络设备被激活的时候被调用(即设备状态由down->up)。
驱动程序作为一个模块被装入:
如果虚接口尚未绑定到物理接口,返回错误信息;否则调用MOD_INC_USE_COUNT宏,以防止模块卸载是设备处于打开状态。
3.2.2.3.5intipsec_tunnel_start_xmit(structsk_buff*skb,structdevice*dev)
目的:
假定此函数由dev_queue_xmit()函数调用,主要负责发送从tcp/udp协议层传来的数据包
参数:
由dev_queue_xmit()函数填充好的skb,及要发往的网络接口
返回值:
0――open成功,非0值――open未成功
算法描述:
1.skb,dev有效吗?
有效继续,无效返回;prv=dev->priv获取ipsec接口私有数据;若prv为空,返回;获取系列参数:
物理接口参数physdev,physmtu,stats;
2.如果需要,拷贝skb:
IfdefNET_21,thenskb_cloned(skb);
3.获取Ip头iph,判断该包是否是IPV4,若不是则丢弃;
4.计算硬件头长度(hard_header_len);
5.将ip包的ttl减小,并计算校验和。
6.填充查找键键值,根据键值查找eroute表,获取eroute,若找到,取出SA,即outgonging_said;
7.判断此IP包是否是IKE协商包(UDPport500),若是,则跳出;
8.进入封装处理大循环(几乎一切处理都由outgoing_said决定,一个said对应一个或多个tdb(通道描述块),根据每个tdb对其进行处理):
(1) checkforDROPormissingeroute
(2) checkforREJECTeroute
(3) checkforPASSeroute
(4) checkforHOLDeroute
(5) checkforTRAPeroute,signalPF_KEY,swaptoHOLDeroute
(6) acquirelockforwalkingtdbchain
(7) calculateheadroomrequiredforchain
1) checkifSAisinlarval,drop
2) checkifSAisdead,drop
3) checkifreplayoverflowed,expireSA
4) checkiflifetimecountershaveoverflowed,expireSA
5) switchonprotocoltype,tocalculateheadroomsize.
I. ifESPswitchonprotocoltypetocalculatetailroomsize.
(8) alculatemtudiff,sendICMPfragmentneeded.Mark``note2''
(9) ackMSSifdesired
(10)copyupper(layer2)headertosafetyifitwaspresent
(11)checkifdatafitsinexistingskb,elseexpand.
(12)applygroupedtransforms
1) applydisasterof#ifdefs.
2) switchbyprotocoltype,calculateheadroomforthisstage
I. ifESP,thenswitchbyciphergetheadroom
II. ifESP,thenswitchbyhashto
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 详细 设计 说明书 示例