?????溯???е?????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);
}