root/net/core/datagram.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_for_packet
  2. skb_recv_datagram
  3. skb_free_datagram
  4. skb_copy_datagram
  5. skb_copy_datagram_iovec
  6. datagram_select

   1 /*
   2  *      SUCS NET3:
   3  *
   4  *      Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
   5  *      of these would make sense. Not tonight however 8-).
   6  *      This is used because UDP, RAW, PACKET, DDP, IPX, AX.25 and NetROM layer all have identical select code and mostly
   7  *      identical recvmsg() code. So we share it here. The select was shared before but buried in udp.c so I moved it.
   8  *
   9  *      Authors:        Alan Cox <alan@cymru.net>. (datagram_select() from old udp.c code)
  10  *
  11  *      Fixes:
  12  *              Alan Cox        :       NULL return from skb_peek_copy() understood
  13  *              Alan Cox        :       Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
  14  *              Alan Cox        :       Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
  15  *                                      AX.25 now works right, and SPX is feasible.
  16  *              Alan Cox        :       Fixed write select of non IP protocol crash.
  17  *              Florian  La Roche:      Changed for my new skbuff handling.
  18  *              Darryl Miles    :       Fixed non-blocking SOCK_SEQPACKET.
  19  *              Linus Torvalds  :       BSD semantic fixes.
  20  *              Alan Cox        :       Datagram iovec handling
  21  *
  22  */
  23 
  24 #include <linux/types.h>
  25 #include <linux/kernel.h>
  26 #include <asm/segment.h>
  27 #include <asm/system.h>
  28 #include <linux/mm.h>
  29 #include <linux/interrupt.h>
  30 #include <linux/in.h>
  31 #include <linux/errno.h>
  32 #include <linux/sched.h>
  33 #include <linux/inet.h>
  34 #include <linux/netdevice.h>
  35 #include <net/ip.h>
  36 #include <net/protocol.h>
  37 #include <net/route.h>
  38 #include <net/tcp.h>
  39 #include <net/udp.h>
  40 #include <linux/skbuff.h>
  41 #include <net/sock.h>
  42 
  43 
  44 /*
  45  * Wait for a packet..
  46  *
  47  * Interrupts off so that no packet arrives before we begin sleeping.
  48  * Otherwise we might miss our wake up
  49  */
  50 static inline void wait_for_packet(struct sock * sk)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         unsigned long flags;
  53 
  54         release_sock(sk);
  55         save_flags(flags);
  56         cli();
  57         if (skb_peek(&sk->receive_queue) == NULL)
  58                 interruptible_sleep_on(sk->sleep);
  59         restore_flags(flags);
  60         lock_sock(sk);
  61 }
  62 
  63 
  64 /*
  65  *      Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
  66  *      races. This replaces identical code in packet,raw and udp, as well as the IPX
  67  *      AX.25 and Appletalk. It also finally fixes the long standing peek and read
  68  *      race for datagram sockets. If you alter this routine remember it must be
  69  *      re-entrant.
  70  *
  71  *      This function will lock the socket if a skb is returned, so the caller
  72  *      needs to unlock the socket in that case (usually by calling skb_free_datagram)
  73  */
  74 
  75 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77         int error;
  78         struct sk_buff *skb;
  79 
  80         lock_sock(sk);
  81 restart:
  82         while(skb_peek(&sk->receive_queue) == NULL)     /* No data */
  83         {
  84                 /* Socket errors? */
  85                 error = sock_error(sk);
  86                 if (error)
  87                         goto no_packet;
  88 
  89                 /* Socket shut down? */
  90                 if (sk->shutdown & RCV_SHUTDOWN)
  91                         goto no_packet;
  92 
  93                 /* Sequenced packets can come disconnected. If so we report the problem */
  94                 error = -ENOTCONN;
  95                 if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
  96                         goto no_packet;
  97 
  98                 /* User doesn't want to wait */
  99                 error = -EAGAIN;
 100                 if (noblock)
 101                         goto no_packet;
 102 
 103                 /* handle signals */
 104                 error = -ERESTARTSYS;
 105                 if (current->signal & ~current->blocked)
 106                         goto no_packet;
 107 
 108                 wait_for_packet(sk);
 109           }
 110 
 111         /* Again only user level code calls this function, so nothing interrupt level
 112            will suddenly eat the receive_queue */
 113         if (flags & MSG_PEEK)
 114         {
 115                 unsigned long flags;
 116                 save_flags(flags);
 117                 cli();
 118                 skb=skb_peek(&sk->receive_queue);
 119                 if(skb!=NULL)
 120                         skb->users++;
 121                 restore_flags(flags);
 122                 if(skb==NULL)           /* shouldn't happen but .. */
 123                         goto restart;
 124                 return skb;
 125         }
 126         skb = skb_dequeue(&sk->receive_queue);
 127         if (!skb)       /* Avoid race if someone beats us to the data */
 128                 goto restart;
 129         skb->users++;
 130         return skb;
 131 
 132 no_packet:
 133         release_sock(sk);
 134         *err = error;
 135         return NULL;
 136 }
 137 
 138 void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         unsigned long flags;
 141 
 142         save_flags(flags);
 143         cli();
 144         skb->users--;
 145         if(skb->users>0)
 146         {
 147                 restore_flags(flags);
 148                 return;
 149         }
 150         /* See if it needs destroying */
 151         if(!skb->next && !skb->prev)    /* Been dequeued by someone - ie it's read */
 152                 kfree_skb(skb,FREE_READ);
 153         restore_flags(flags);
 154         release_sock(sk);
 155 }
 156 
 157 /*
 158  *      Copy a datagram to a linear buffer.
 159  */
 160 
 161 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163         memcpy_tofs(to,skb->h.raw+offset,size);
 164 }
 165 
 166 
 167 /*
 168  *      Copy a datagram to an iovec.
 169  */
 170  
 171 void skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         memcpy_toiovec(to,skb->h.raw+offset,size);
 174 }
 175 
 176 /*
 177  *      Datagram select: Again totally generic. Moved from udp.c
 178  *      Now does seqpacket.
 179  */
 180 
 181 int datagram_select(struct sock *sk, int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         select_wait(sk->sleep, wait);
 184         switch(sel_type)
 185         {
 186                 case SEL_IN:
 187                         if (sk->err)
 188                                 return 1;
 189                         if (sk->shutdown & RCV_SHUTDOWN)
 190                                 return 1;
 191                         if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
 192                         {
 193                                 /* Connection closed: Wake up */
 194                                 return(1);
 195                         }
 196                         if (skb_peek(&sk->receive_queue) != NULL)
 197                         {       /* This appears to be consistent
 198                                    with other stacks */
 199                                 return(1);
 200                         }
 201                         return(0);
 202 
 203                 case SEL_OUT:
 204                         if (sk->err)
 205                                 return 1;
 206                         if (sk->shutdown & SEND_SHUTDOWN)
 207                                 return 1;
 208                         if (sk->type==SOCK_SEQPACKET && sk->state==TCP_SYN_SENT)
 209                         {
 210                                 /* Connection still in progress */
 211                                 break;
 212                         }
 213                         if (sk->prot && sock_wspace(sk) >= MIN_WRITE_SPACE)
 214                         {
 215                                 return(1);
 216                         }
 217                         if (sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
 218                         {
 219                                 return(1);
 220                         }
 221                         return(0);
 222 
 223                 case SEL_EX:
 224                         if (sk->err)
 225                                 return(1); /* Socket has gone into error state (eg icmp error) */
 226                         return(0);
 227         }
 228         return(0);
 229 }

/* [previous][next][first][last][top][bottom][index][help] */