Chinaunix首页 | 论坛 | 博客
  • 博客访问: 234759
  • 博文数量: 48
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 548
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-28 19:18
文章分类

全部博文(48)

文章存档

2010年(6)

2009年(6)

2008年(36)

我的朋友

分类: LINUX

2009-02-11 10:26:10

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()函数放入网络协议hashinet_protos[MAX_INET_PROTOS],其中MAX_INET_PROTOS宏的定义为256

代码为:if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)

       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  *uhUDP头结构体,具体定义在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/

阅读(2088) | 评论(0) | 转发(0) |
0

上一篇:linux驱动学习步骤

下一篇:WMD驱动

给主人留下些什么吧!~~