免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1359 | 回复: 0
打印 上一主题 下一主题

LINUX2.6.18-i386内核UDP包进站流程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-11 10:26 |只看该作者 |倒序浏览
LINUX2.6.18-i386内核UDP包进站流程
l  UDP包处理系列函数的注册
在af_inet.c文件中声明的UDP协议处理函数结构体
static struct net_protocol udp_protocol = {
    .handler = udp_rcv,
    .err_handler =    udp_err,
    .no_policy =  1,
};
通过inet_add_protocol()函数放入网络协议hash表inet_protos[MAX_INET_PROTOS]中,其中MAX_INET_PROTOS宏的定义为256。
代码为:if (inet_add_protocol(&udp_protocol, IPPROTO_UDP)
       printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n");
其中IPPROTO_UDP宏是在in.h中定义的,值为17,即此结构体被映射到inet_protos数组的第17个元素的位置。
udp_protocol.handler被赋值为udp_rcv()函数,此函数是UDP协议的进站处理函数接口,其函数原型在/usr/src/linux-2.6.18.i386/net/ipv4/udp.c文件中被定义;inet_add_protocol的函数原型在protocol.c文件中定义,struct net_protocol结构体在protocol.h中定义。
struct net_protocol {
    int        (*handler)(struct sk_buff *skb);
    void          (*err_handler)(struct sk_buff *skb, u32 info);
    int        (*gso_send_check)(struct sk_buff *skb);
    struct sk_buff           *(*gso_segment)(struct sk_buff *skb,
                         int features);
    int        no_policy;
};
l  UDP包处理函数的调用流程
从网卡过来的数据包在通过第二个钩子NF_IP_LOCAL_IN时,调用钩子处理函数ip_local_deliver_finish()函数对数据包的协议和本机初始化是注册的协议处理函数进行匹配,根据数据包头中的协议值在inet_protos数组中找到相对应的包处理结构体,根据结构体中指定的函数进行下一步的处理。(函数代码在ip_input.c中)
l  UDP进站包中获得端口号
在从网卡获得的sk_buff包结构中的共用体h中有一项struct udphdr  *uh为UDP头结构体,具体定义在usr/src/linux-2.6.18.i386/include/linux/udp.h中,此结构体有四个成员,分别为:发送端主机端口号、接收端主机端口号、UDP包长度和校验和。如想获取端口号可根据实际需要通过ntohs()函数将相应的端口号从网络字节序转换为主机字节序即可。
例:
如A主机往B主机发送UDP包,获取A主机设定的UDP端口号可使用ntohs(skb->h.uh->dest)获得。


struct sk_buff结构体在skbuff.h中
struct sk_buff {
    /* These two members must be first. */
    struct sk_buff       *next;
    struct sk_buff       *prev;


    struct sock       *sk;
    struct skb_timeval   tstamp;
    struct net_device *dev;
    struct net_device *input_dev;


    union {
       struct tcphdr *th;
       struct udphdr *uh;
       struct icmphdr    *icmph;
       struct igmphdr    *igmph;
       struct iphdr  *ipiph;
       struct ipv6hdr    *ipv6h;
       unsigned char *raw;
    } h;


    union {
       struct iphdr  *iph;
       struct ipv6hdr    *ipv6h;
       struct arphdr *arph;
       unsigned char *raw;
    } nh;


    union {
        unsigned char     *raw;
    } mac;


    struct  dst_entry *dst;
    struct sec_path   *sp;


    /*
     * This is the control buffer. It is free to use for every
     * layer. Please put your private variables there. If you
     * want to keep them across layers you have to do a skb_clone()
     * first. This is owned by whoever has the skb queued ATM.
     */
    char          cb[48];


    unsigned int      len,
              data_len,
              mac_len,
              csum;
    __u32         priority;
    __u8          local_df:1,
              cloned:1,
              ip_summed:2,
              nohdr:1,
              nfctinfo:3;
    __u8          pkt_type:3,
              fclone:2,
#ifndef CONFIG_XEN
              ipvs_property:1;
#else
              ipvs_property:1,
              proto_data_valid:1,
              proto_csum_blank:1;
#endif
    __be16        protocol;


    void          (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
    struct nf_conntrack  *nfct;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
    struct sk_buff       *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
    struct nf_bridge_info    *nf_bridge;
#endif
    __u32         nfmark;
#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_NET_SCHED
    __u16         tc_index;  /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
    __u16         tc_verd;   /* traffic control verdict */
#endif
#endif
#ifdef CONFIG_NET_DMA
    dma_cookie_t      dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
    __u32         secmark;
#endif




    /* These elements must be at the end, see alloc_skb() for details.  */
    unsigned int      truesize;
    atomic_t      users;
    unsigned char     *head,
              *data,
              *tail,
              *end;
};
路径说明:
af_inet.c         /usr/src/linux-2.6.18.i386/net/ipv4/
in.h              /usr/src/linux-2.6.18.i386/include/linux/
ip_input.c    /usr/src/linux-2.6.18.i386/net/ipv4/
protocol.c    /usr/src/linux-2.6.18.i386/net/ipv4/
protocol.h    /usr/src/linux-2.6.18.i386/include/net/
skbuff.h          /usr/src/linux-2.6.18.i386/include/linux/


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/72457/showart_1823640.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP