BSD TCP/IP协议栈 地址结构

来源:互联网 发布:安德鲁拜纳姆 知乎 编辑:程序博客网 时间:2024/05/13 09:56

 

   BSD TCP/IP 协议栈已经快一个月了,从刚开始的茫无头绪,到今天的稍微有点头绪,还是有点收获的。今天想写点关于协议栈源码中,各种地址结构的联系。
   我们都知道TCP/IP是分四层架构的,从底往上分别为数据链路层,网络层(IPICMPIGMP),运输层(TCPUDP),和应用层。而链路层所用的地址跟运输层所用的地址是不同的。比如一个链路层使用以太网接口的主机,数据包在链路层处理的时候是使用48位硬件地址的,而IP层所用的是32IP地址。我们在这里不讨论IP地址与硬件地址的转换,而只关注BSD中,对这些不同层次地址的抽象。其整体的结构如图1.1所示。
   我们看到协议栈为了与具体的硬件分离,抽象出了接口(interface)的概念。它用struct ifnet 的结构表示,其中包含了协议栈与硬件交互所必须的所有信息,它的第一个成员name指明了这个接口的类型。而所有的接口都通过结构体中的if_next指针连接在一起,全局变量ifnet指向队列的第一个元素。如图中,共有三个接口,分别是lethersliploopback,代表了以太网接口,串行接口,本地回环接口。
   下面继续看地址结构,因为不同的协议规定了不同类型的地址,所以它们在源码中的结构体都是不同的。但协议栈为了方便表示与使用,在这些协议相关的地址结构的基础上抽象出了一个与具体协议无关的struct ifaddr结构,其具体的成员组成如下:
 
   Struct ifaddr{
        Struct sockaddr* ifa_addr;
        Struct sockaddr* ifa_destaddr;
        Struct sockaddr* ifa_netmask;
        Struct ifnet* ifa_ifp;
        Struct ifaddr* ifa_next;
        Struct (*ifa_rtrequest)();
        U_short ifa_flags;
        Short ifa_refcnt;
        Int ifa_metric;
        Struct rtentry *ifa_rt;
};
   因为很多的接口,比如以太网接口可以有不止一个地址,所以在ifnet结构中,有一个if_addrlist成员,指向了所有属于这个接口的ifaddr结构,ifaddr结构中的ifa_next指向下一个if_addrlist结构。还有需要注意的是ifaddr结构中还有一个sockaddr类型的结构,它是比ifaddr更加精确的地址描述,这个也是与协议无关的。
下面开始进入对协议栈不同层次地址结构的描述。首先我们看数据链路层的地址描述。链路层的地址结构有一个ifaddr结构和两个sockaddr_dl结构组成,而两个sockaddr_dl是紧接着ifaddr结构的,其中第一个sockaddr_dl中存放了链路层地址,第二个sockaddr_dl存放的是链路层地址掩码。链路层地址掩码的作用我也没弄清楚,如果有哪位大侠知道,请留言哈。
所有的链路层地址都存放在ifnet_addrs数组中,注意,ifnet_addrs是一个指针数组,而不是指向链表首地址的指针。在sockaddr_dl中有一个sdl_index成员,用来找到相应的ifaddr结构。这是这个数组的唯一用处。
对于以太网接口来讲,链路层ifaddr结构中的ifa_next指向的就是ip层地址了。Ip地址用in_ifaddr结构来描述。这个结构的第一个成员就是ifaddr,用来描述协议无关的成员。其余的就是协议相关的成员了。所有ip层的地址都被链接在一起,其中全局变量in_ifaddrs指向该链表的第一个元素,in_ifaddr中的ia_next指向下一个in_ifaddr结构。这个链表用的比较多,在ip层收发数据时,会扫描这个链表来寻找数据包所对应的in_ifaddr结构。


                                                                        1.1

 

原创粉丝点击