5,530
社区成员
发帖
与我相关
我的任务
分享
/*udp层的数据接收
udp层的数据接收,对于socket而言,就是接收队列的入队操作。在ip层中,如果是本地数据,则会交由ip_local_deliver_finish()函数处理,它会根据传输层协议的类型,交由相应的处理函数,对于udp协议而言,就是udp_rcv():*/
[Copy to clipboard] [ - ]
CODE:
/*
* All we need to do is get the socket, and then do a checksum.
*/
int udp_rcv(struct sk_buff *skb)
{
struct sock *sk;
struct udphdr *uh;
unsigned short ulen;
dst;
saddr;
daddr;
len;
/*
* 数据包至少应有UDP首部长度.
*/
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
goto no_header;
/*获取udp首部指针*/
h.uh;
/* 数据长度,含首部长度 */
len);
/* 数据包长度不够:UDP长度比skb长度小,意味着数据的丢失,而udp长度比udp首部还要小,好像这个不太可能,除非封包出错 ^o^*/
len || ulen
goto short_packet;
/* 截去udp报文后面的多余报文 */
if (pskb_trim(skb, ulen))
goto short_packet;
/* 开始udp校验和计算,主要查依赖于skb的ip_summumed字段的设置来决定是否需要进行校验和计算 */
if (udp_checksum_init(skb, uh, ulen, saddr, daddr)
goto csum_error;
/* 转换多播或广播处理例程 */
rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
/* 查找数据段对应的socket结构的sk */
ifindex);
if (sk != NULL) {
/* 找到了,数据包进入UDP的socket的接收队列*/
int ret = udp_queue_rcv_skb(sk, skb);
sock_put(sk);
0 means to resubmit the input, but
* it it wants the return to be -protocol, or 0
*/
0)
return -ret;
return 0;
}
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto drop;
/* 没有对应的socket. 如果校验和错误,则丢弃它 */
if (udp_checksum_complete(skb))
goto csum_error;
/* 发送一个目的不可达报文 */
UDP_INC_STATS_BH(UDP_MIB_NOPORTS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
/*
* Hmm. We got an UDP packet to a port to which we
* don't wanna listen. Ignore it.
*/
kfree_skb(skb);
return(0);
short_packet:
NETDEBUG(if (net_ratelimit())
printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
NIPQUAD(saddr),
source),
ulen,
len,
NIPQUAD(daddr),
dest)));
no_header:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
kfree_skb(skb);
return(0);
csum_error:
/*
* RFC1122: OK. Discards the bad packet silently (as far as
* the network is concerned, anyway) as per 4.1.3.4 (MUST).