分类:
2010-08-23 15:55:44
1 服务提供者分为传输服务提供者与名字空间服务提供者两种。这里只讨论了传输服务提供者。
2 这里基础服务提供者理解得比较透彻,第二与第四部分都是基础服务提供者;分层服务提供者与协议链服务提供者理解得不太清楚,见第三部分。
3 欢迎高手指正其中的错误或点明我的疑惑
四 我们公司的产品中安装及使用基础服务提供者的方法... 4
服务提供者以动态库的形式存在。一个动态库可以提供多个服务提供者。
每个服务提供者有一个WSAPROTOCOL_INFOW类型的结构对象,表示该服务提供者的一些信息, 当一个服务提供者所在的动态库被加载并且其WSPStartup被调用的时候,在WSPStartup中传进来的WSAPROTOCOL_INFOW参数就是这个服务提供者对应的WSAPROTOCOL_INFOW的结构信息。该结构中有一个WSAPROTOCOLCHAIN ProtocolChain成员,
typedef struct _WSAPROTOCOLCHAIN {
int ChainLen; /* the length of the chain, */
/* length = 0 means layered protocol, */
/* length = 1 means base protocol, */
/* length > 1 means protocol chain */
DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; /* a list of dwCatalogEntryIds */
} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;
它有两个成员,ChainLen与ChainEntries[]。
ChainLen如果是0或者1分别表示该服务提供者是分层或者基础服务提供者,这个比较简单,如果ChainLen的值大于1,表示该服务提供者是一个协议链服务提供者,这比较复杂点,1 这时ChainLen的值表示ChainEntries[]数组中的项数,
2 ChainEntries[]数组中的每一项的值是协议链上各个服务提供者的WSAPROTOCOL_INFOW结构中的dwCatalogEntryId,根据这个值可以找到相应的服务提供者,(可以通过dwCatalogEntryId找到WSAPROTOCOL_INFOW结构对象,然后通过WSAPROTOCOL_INFOW结构对象找到对应的动态库的路径)
3 最后一项代表的服务提供者是当前WSAPROTOCOL_INFOW对应的服务提供者的下一层服务提供者,
4 第一项代表的服务提供者是根分层服务提供者。
每个服务提供者对应的的WSAPROTOCOL_INFOW结构信息,保存在注册表中,同时保存在注册表中的还有:服务提供者的路径,加载顺序。保存方式是二进制的,必须通过工具识别,如SPORDER.EXE/SPORDER.DLL。
1 找到要被替换的基础服务提供者,HOW?
从注册表中遍历所有的服务提供者,然后根据WSAPROTOCOL_INFOW结构中的信息来判断是否是要被替换的服务提供者;Windows也提供了枚举并得到所有服务提供者WSAPROTOCOL_INFOW结构的API。
2 找到要被替换的基础服务提供者的动态库的路径,HOW?
能够从注册表中得到; Windows也提供了根据WSAPROTOCOL_INFOW结构得到动态库路径的API。
3 保存该路径到注册表中,HOW
注册表操作,
4 替换要被替换的基础服务提供者的动态库的路径为自己的路径,HOW?
注册表操作
1 当原服务提供者被加载以及其WSPStartup被调用时,实际上被加载并被调用的是新的基础服务提供者的DLL以及其WSPStartup。因为加载者是根据路径来加载的,而路径已经被替换。
2 新的WSPStartup的实现会去找到原服务提供者的路径,加载并调用其WSPStartup,目的从原服务提供者那里获得30个函数指针,调用时的参数无需改变。
3 新的WSPStartup根据自己的需求做一些特定的实现。
分层服务提供者的安装,还需要安装协议链服务提供者;先安装分层服务提供者,然后构造协议链服务提供者的WSAPROTOCOL_INFOW结构,通过该结构将分层服务提供者,以及相关的基础服务提供者组织起来,然后安装该协议链服务提供者。安装完协议链服务提供者了之后,将协议链服务提供者的顺序排在所有提供者中的第一个。
系统根据注册表中的服务提供者的顺序来找到第一个合适的服务提供者,加载并对其进行调用。
总的来说,分层服务提供者/协议链服务提供者的使用方式比较复杂,看到的各种例子的使用方式也不完全一样。有一些疑惑的地方,见下面的【问题】。
1 找到协议链服务提供者所需要的下一层服务提供者的WSAPROTOCOL_INFOW信息,拷贝一份,
2 在副本上修改以构造分层服务提供者的WSAPROTOCOL_INFOW结构,包括修改名字,修改ProtocolChain.ChainLen的值为0,然后安装,安装的时候提供分层服务提供者的GUID以及动态库的路径,GUID可以通过命令行工具UUIDGEN或者编程中是用UuidCreate函数生成,
3安装完了之后,WS2_32.lib会为这个分层服务提供者提供一个dwCatalogEntryId
4 再拷贝一份协议链服务提供者的下一层服务提供者的WSAPROTOCOL_INFOW信息,在副本上修改以构造协议链服务提供者的WSAPROTOCOL_INFOW结构。需要在副本上修改ProtocolChain.ChainEntries[]的值,设置第一项为根分成服务提供者的dwCatalogEntryId,最后一项设置为副本的,也就是下一层服务提供者的dwCatalogEntryId,然后将副本的ProtocolChain.ChainLen的值加一。安装的时候提供一个协议链服务提供者的GUID,以及与分层服务提供者相同的动态库路径,因为两者是同一个动态库提供的。
4安装完了之后,WS2_32.lib会为这个新的协议链服务提供者提供一个dwCatalogEntryId,调用系统提供的API通过dwCatalogEntryId将服务提供者排序,把协议链服务提供者放在最上面。
1 协议链服务提供者在安装的时候被放在了最上面,所以协议链服务提供者最先被加载并被调用WSPStartup,
2因为是协议链服务提供者,所以参数中的WSAPROTOCOL_INFOW结构中的ProtocolChain.ChainLen必须大于1,且其值表示ProtocolChain.ChainEntries[]数组中的元素个数,最后一个,即ProtocolChain.ChainEntries[ProtocolChain.ChainLen-1]就是下一层服务提供者的WSAPROTOCOL_INFOW结构中的dwCatalogEntryId.
3 根据dwCatalogEntryId,遍历所有的服务提供者找到下一层服务提供者,加载并调用其WSPStartup获得30个函数指针。
1 根分层服务提供者的作用是什么?个人觉得它没有存在的必要,也没看到它发挥了什么必要的作用,只需要直接构造并安装协议链服务提供者即可。
2 被安装的新的协议链服务提供者与被安装的新的基础服务提供者的根本区别在哪里。
3 以上安装以及工作原理均基于朱雁辉著的《防火墙与网络封包截获技术》一书,但网上也有其它的例子,使用方法与之不同,难道没有一个统一的使用标准,还是说不同的方法各成一家,只要安装的方法与使用的方法能够配合起来使用就行。
在第二部分中提到,安装基础服务提供者不需要在注册表中新增项,只需要替换路径即可,但这是不一定的,也可以像第三部分中那样调用系统API来新增注册表中的项,
无论是使用上文中修改下一层服务提供者路径的方法,还是通过协议链方式保存下一层dwCatalogEntryId的值的方式,其目的都是让新的服务提供者能找到下一层服务提供者。
我们公司的产品使用的方法是直接安装新的基础服务提供者,然后在新的服务提供者的WSPStartup里面遍历所有的服务提供者,根据GUID显式的寻找已知GUID的下一层服务提供者,安装基础服务提供者的方法有别于第二部分中提到的方法。
1 朱雁辉编著的《防火墙与网络封包截获技术》
2 网络文章《基于SPI的数据报过滤原理与实现》