完成MY_PF_INET域的初始化

来源:互联网 发布:sjf算法例题 编辑:程序博客网 时间:2024/05/21 22:21


   前面两篇中,我们已经做了两步关于family初始化的工作:创建并注册了family中的三种协议:TCP, UDP和RAW;向net_families数组注册我们的MY_PF_INET域。
    接下来,我们描述其余的要做的初始化工作,其实很多工作我们并没有真正完成,大多数只是留下一个空的函数,先使它们具备一个框架,留待日后完善。
    第三步,我们添加一些基本的协议,分别是TCP, UDP, ICMP, IGMP。这在概念上可能点混乱,暂且不管,先关注其实现。有一个数组:
        struct net_protocol *inet_protos[MAX_INET_PROTOS];
        #define MAX_INET_PROTOS 256
它包含了当前系统中所有已添加的协议,结构struct net_protocol用于注册协议,其内容很简单:
        struct net_protocol {
            int  (*handler)(struct sk_buff *skb);
            void (*err_handler) (struct sk_buff * skb, u32 info);
            int  no_policy;
        };
现在碰到一个问题,即TCP, UDP, ICMP, IGMP协议已经由真正的PF_INET域注册到数组中了,我们这个假冒的MY_PF_INET域再要使用数组中的这些项,肯定会失败,所以,我们继续寻找空项:
        #define MY_IPPROTO_ICMP     (IPPROTO_ICMP + 60)
        #define MY_IPPROTO_IGMP     (IPPROTO_IGMP + 60)
        #define MY_IPPROTO_TCP      (IPPROTO_TCP + 60)
        #define MY_IPPROTO_UDP      (IPPROTO_UDP + 60)
必须要说明的是,这是一个很危险的动作,因为我们不能保证IPPROTO_ICMP+60是未使用的。
    第四步,初始化inetsw数组,inetsw的每一项是一个链表,链表中所有的项都是一个struct inet_protosw,并且同一个链表中的结构体具有相同的套接字类型。在MY_PF_INET域中,我们有三个inet_protosw,分别是:     static struct inet_protosw myinetsw_array[] =
    {
        {
            .type =         SOCK_STREAM,
            .protocol =     MY_IPPROTO_TCP,
            .prot =         &mytcp_prot,
            .ops =          &myinet_stream_ops,
            .capability =   -1,
            .no_check =     0,
            .flags =        INET_PROTOSW_PERMANENT,
        },

        {
            .type =       SOCK_DGRAM,
            .protocol =   MY_IPPROTO_UDP,
            .prot =       &myudp_prot,
            .ops =        &myinet_dgram_ops,
            .capability = -1,
            .no_check =   UDP_CSUM_DEFAULT,
            .flags =      INET_PROTOSW_PERMANENT,
        },

        {
            .type =       SOCK_RAW,
            .protocol =   IPPROTO_IP,   /* wild card */
            .prot =       &myraw_prot,
            .ops =        &myinet_sockraw_ops,
            .capability = CAP_NET_RAW,
            .no_check =   UDP_CSUM_DEFAULT,
            .flags =      INET_PROTOSW_REUSE,
        }
    }
    它们分别放入inetsw中,各占一项,不会形成链表。这里容易混淆的是prot跟ops,它们提供相似的接口。但它们在层次上是有所差异的,比如 SOCK_STREAM中,prot是tcp协议相关的操作,而ops是inet域中流协议相关的操作。
    第五步,各个模块的初始化,包括tcp, ip, ip_fragment, arp等等,我们暂时全部留空,不追究其细节。
    第六步,向网络栈添加一个协议处理器。inet域的协议处理结构如下:
        static struct packet_type myip_packet_type = {
            .type = __constant_htons(ETH_P_IP),
            .func = myip_rcv,
        };
    该结构最终被加入static struct list_head ptype_base[16],从而完成添加工作。