上面函数中调用了get_sock_mcast()函数,下面具体分析一下该函数的功能,该函数定义的位置在文件af_inet.c中


/*
 * Deliver a datagram to broadcast/multicast sockets.
 */
 
struct sock *get_sock_mcast(struct sock *sk, //套接字指针
    unsigned short num,//本地端口
    unsigned long raddr,//远端地址
    unsigned short rnum,//远端端口
    unsigned long laddr)//本地地址
{
 struct sock *s;
 unsigned short hnum;

 hnum = ntohs(num);

 /*
  * SOCK_ARRAY_SIZE must be a power of two.  This will work better
  * than a prime unless 3 or more sockets end up using the same
  * array entry.  This should not be a problem because most
  * well known sockets don't overlap that much, and for
  * the other ones, we can just be careful about picking our
  * socket number when we choose an arbitrary one.
  */
 
 s=sk;

 for(; s != NULL; s = s->next)
 {
  if (s->num != hnum) //本地端口不符合,跳过
   continue;
  if(s->dead && (s->state == TCP_CLOSE))//dead=1表示该sock结构已经处于释放状态
   continue;
  if(s->daddr && s->daddr!=raddr)//sock的远端地址不等于条件中的远端地址
   continue;
  if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0)
   continue;
   if(s->saddr  && s->saddr!=laddr)//sock的本地地址不等于条件的本地地址
   continue;
  return(s);
   }
   return(NULL);
}
 


  下面是udp_rcv调用的udp_deliver()函数


static int udp_deliver(struct sock *sk,//sock结构指针
      struct udphdr *uh,//UDP头指针
      struct sk_buff *skb,//sk_buff
      struct device *dev,//接收的网络设备
      long saddr,//本地地址
      long daddr,//远端地址
      int len)//数据包的长度
{
 //对skb结构相应字段赋值
 skb->sk = sk;
 skb->dev = dev;
 //skb->len = len;

 /*
  * These are supposed to be switched.
  */
 
 skb->daddr = saddr;//设置目的地址为本地地址
 skb->saddr = daddr;//设置源地址为远端地址


 /*
  * Charge it to the socket, dropping if the queue is full.
  */

 skb->len = len - sizeof(*uh); 
 
 if (sock_queue_rcv_skb(sk,skb)<0) //调用sock_queu_rcv_skb()函数,将skb挂到sk接构中的接收队列中
 {
  udp_statistics.UdpInErrors++;
  ip_statistics.IpInDiscards++;
  ip_statistics.IpInDelivers--;
  skb->sk = NULL;
  kfree_skb(skb, FREE_WRITE);
  release_sock(sk);
  return(0);
 }
   udp_statistics.UdpInDatagrams++;
 release_sock(sk);
 return(0);
}