Chinaunix首页 | 论坛 | 博客
  • 博客访问: 88491
  • 博文数量: 25
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-19 13:51
文章分类
文章存档

2016年(19)

2015年(3)

2014年(3)

我的朋友

分类: LINUX

2016-06-01 17:45:44


点击(此处)折叠或打开

  1. /*...直接就来函数调用... */
  2. int udp_rcv(struct sk_buff *skb)
  3. {
  4.     return __udp4_lib_rcv(skb, udp_hash, IPPROTO_UDP);
  5. }

  6. /*
  7.  *    All we need to do is get the socket, and then do a checksum.
  8.  */
  9. int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
  10.          int proto)
  11. {
  12.     struct sock *sk;
  13.     struct udphdr *uh = udp_hdr(skb);
  14.     unsigned short ulen;
  15.     struct rtable *rt = (struct rtable*)skb->dst;
  16.     __be32 saddr = ip_hdr(skb)->saddr;
  17.     __be32 daddr = ip_hdr(skb)->daddr;

  18.     /*
  19.      * Validate the packet.
  20.      */
  21.     /* 确保udp头部在线性数据缓冲区中 */
  22.     if (!pskb_may_pull(skb, sizeof(struct udphdr)))
  23.         goto drop;        /* No space for header. */

  24.     ulen = ntohs(uh->len);
  25.     /* udp头部指定该upd长度比skb总数据长度还大,显然是一个错误 */
  26.     if (ulen > skb->len)
  27.         goto short_packet;
  28.     /* UDP-Lite协议不必进行len validate。因为其头部的len字段表示的校验的长度 */
  29.     if (proto == IPPROTO_UDP) {
  30.         /* UDP validates ulen. */
  31.     /* 该包的长度至少是一个UDP头部长度,将该包trim到ulen长度 */
  32.         if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
  33.             goto short_packet;
  34.         uh = udp_hdr(skb);
  35.     }
  36.     /* 校验和初始化,若udp头部的校验和字段为0,则设置不必校验标志位,若校验由硬
  37.      * 完成,且伪首部通过校验,则同样设置不必校验标志,若以上都不满足,则将伪首
  38.      * 部的校验和给skb->csum,之后还需要对数据部分进行校验,但这不是该函数的工
  39.      * 作,错误只可能发生在对UDP-Lite协议的包进行校验,暂不考虑。 */
  40.     if (udp4_csum_init(skb, uh, proto))
  41.         goto csum_error;

  42.     /* 广播包或者是多播包...暂不考虑 */
  43.     if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
  44.         return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);

  45.     /* 接收udp包的上层应用对应的sock都组织在udptable这个以注册端口为关键字的
  46.      * 哈希表中,该函数遍历哈希槽找最满足匹配条件的sock并返回它,匹配的字段包括
  47.      * 地址域是否是PF_INET,源、目的地址是否匹配,端口是否匹配,绑定的外出接口
  48.      * 设备是否匹配。匹配项最多的获胜。 */
  49.     sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
  50.              inet_iif(skb), udptable);
  51.     /* 这表明有上层应用需要接收这个包, */
  52.     if (sk != NULL) {
  53.     /* 将该包挂入到套接字的等待队列,并唤醒等待该套接字中的数据的进程 */
  54.         int ret = udp_queue_rcv_skb(sk, skb);
  55.         sock_put(sk);

  56.         /* a return value > 0 means to resubmit the input, but
  57.          * it wants the return to be -protocol, or 0
  58.          */
  59.         if (ret > 0)
  60.             return -ret;
  61.         return 0;
  62.     }
  63.     /* 下面的就暂不操心了...*/

  64.     if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  65.         goto drop;
  66.     nf_reset(skb);

  67.     /* No socket. Drop packet silently, if checksum is wrong */
  68.     if (udp_lib_checksum_complete(skb))
  69.         goto csum_error;

  70.     UDP_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
  71.     icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);

  72.     /*
  73.      * Hmm. We got an UDP packet to a port to which we
  74.      * don't wanna listen. Ignore it.
  75.      */
  76.     kfree_skb(skb);
  77.     return 0;

  78. short_packet:
  79.     LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
  80.          proto == IPPROTO_UDPLITE ? "-Lite" : "",
  81.          NIPQUAD(saddr),
  82.          ntohs(uh->source),
  83.          ulen,
  84.          skb->len,
  85.          NIPQUAD(daddr),
  86.          ntohs(uh->dest));
  87.     goto drop;

  88. csum_error:
  89.     /*
  90.      * RFC1122: OK. Discards the bad packet silently (as far as
  91.      * the network is concerned, anyway) as per 4.1.3.4 (MUST).
  92.      */
  93.     LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
  94.          proto == IPPROTO_UDPLITE ? "-Lite" : "",
  95.          NIPQUAD(saddr),
  96.          ntohs(uh->source),
  97.          NIPQUAD(daddr),
  98.          ntohs(uh->dest),
  99.          ulen);
  100. drop:
  101.     UDP_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
  102.     kfree_skb(skb);
  103.     return 0;
  104. }

阅读(2333) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~