root/net/socket/datagram.c

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

DEFINITIONS

This source file includes following definitions.
  1. skb_recv_datagram
  2. skb_free_datagram
  3. skb_copy_datagram
  4. datagram_select

   1 /*
   2  *      SUCS    NET2 Debugged.
   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 and the to be released IPX layer all have identical select code and mostly
   7  *      identical recvfrom() 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 <iiitac@pyr.swan.ac.uk>. (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        :       Tidied up ready for the big day.
  17  *              Alan Cox        :       Fixed write select of no IP protocol crash.
  18  */
  19 
  20 #include <linux/config.h>
  21 #include <linux/types.h>
  22 #include <linux/kernel.h>
  23 #include <asm/segment.h>
  24 #include <asm/system.h>
  25 #include <linux/mm.h>
  26 #include <linux/interrupt.h>
  27 #include <linux/in.h>
  28 #include <linux/errno.h>
  29 #include <linux/sched.h>
  30 #include "inet.h"
  31 #include "dev.h"
  32 #include "ip.h"
  33 #include "protocol.h"
  34 #include "arp.h"
  35 #include "route.h"
  36 #include "tcp.h"
  37 #include "udp.h"
  38 #include "skbuff.h"
  39 #include "sock.h"
  40  
  41 
  42 /*
  43  *      Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
  44  *      races. This replaces identical code in packet,raw and udp, as well as the yet to
  45  *      be released IPX support. It also finally fixes the long standing peek and read
  46  *      race for datagram sockets. If you alter this routine remember it must be
  47  *      re-entrant.
  48  */
  49 
  50 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {  
  52         struct sk_buff *skb;
  53         
  54         /* Socket is inuse - so the timer doesn't attack it */
  55 restart:
  56         sk->inuse = 1;
  57         while(sk->rqueue == NULL)       /* No data */
  58         {
  59                 /* If we are shutdown then no more data is going to appear. We are done */
  60                 if (sk->shutdown & RCV_SHUTDOWN) 
  61                 {
  62                         release_sock(sk);
  63                         *err=0;
  64                         return NULL;
  65                 }
  66 
  67                 if(sk->err)
  68                 {
  69                         release_sock(sk);
  70                         *err=-sk->err;
  71                         sk->err=0;
  72                         return NULL;
  73                 }
  74                 
  75                 /* Sequenced packets can come disconnected. If so we report the problem */
  76                 if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
  77                 {
  78                         release_sock(sk);
  79                         *err=-ENOTCONN;
  80                         return NULL;
  81                 }
  82                 
  83                 /* User doesn't want to wait */
  84                 if (noblock) 
  85                 {
  86                         release_sock(sk);
  87                         *err=-EAGAIN;
  88                         return NULL;
  89                 }
  90                 release_sock(sk);
  91                 
  92                 /* Interrupts off so that no packet arrives before we begin sleeping. 
  93                    Otherwise we might miss our wake up */
  94                 cli();
  95                 if (sk->rqueue == NULL) 
  96                 {
  97                         interruptible_sleep_on(sk->sleep);
  98                         /* Signals may need a restart of the syscall */
  99                         if (current->signal & ~current->blocked) 
 100                         {
 101                                 sti();
 102                                 *err=-ERESTARTSYS;
 103                                 return(NULL);
 104                         }
 105                         if(sk->err != 0)        /* Error while waiting for packet
 106                                                    eg an icmp sent earlier by the
 107                                                    peer has finaly turned up now */
 108                         {
 109                                 *err = -sk->err;
 110                                 sti();
 111                                 sk->err=0;
 112                                 return NULL;
 113                         }
 114                 }
 115                 sk->inuse = 1;
 116                 sti();
 117           }
 118           /* Again only user level code calls this function, so nothing interrupt level
 119              will suddenely eat the rqueue */
 120           if (!(flags & MSG_PEEK)) 
 121           {
 122                 skb=skb_dequeue(&sk->rqueue);
 123                 if(skb!=NULL)
 124                         skb->users++;
 125                 else
 126                         goto restart;   /* Avoid race if someone beats us to the data */
 127           }
 128           else
 129           {
 130                 cli();
 131                 skb=skb_peek(&sk->rqueue);
 132                 if(skb!=NULL)
 133                         skb->users++;
 134                 sti();
 135                 if(skb==NULL)   /* shouldn't happen but .. */
 136                         *err=-EAGAIN;
 137           }
 138           return skb;
 139 }       
 140 
 141 /*
 142  *      Free a datagram buffer. This has some conditions to watch. We keep
 143  *      a user count so the last user may free the buffer. If however the
 144  *      buffer has a valid next pointer it was never removed and all the
 145  *      users PEEKed at it - so don't free it yet.
 146  */
 147  
 148 void skb_free_datagram(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150         unsigned long flags;
 151 
 152         save_flags(flags);
 153         cli();
 154         skb->users--;
 155         if(skb->users>0)
 156         {
 157                 restore_flags(flags);
 158                 return;
 159         }
 160         /* See if it needs destroying */
 161         if(skb->list == NULL)   /* Been dequeued by someone - ie its read */
 162                 kfree_skb(skb,FREE_READ);
 163         restore_flags(flags);
 164 }
 165 
 166 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         /* We will know all about the fraglist options to allow >4K receives 
 169            but not this release */
 170         memcpy_tofs(to,skb->h.raw+offset,size);
 171 }
 172 
 173 /*
 174  *      Datagram select: Again totally generic. Moved from udp.c
 175  *      Now does seqpacket.
 176  */
 177  
 178 int datagram_select(struct sock *sk, int sel_type, select_table *wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         select_wait(sk->sleep, wait);
 181         switch(sel_type) 
 182         {
 183                 case SEL_IN:
 184                         if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
 185                         {
 186                                 /* Connection closed: Wake up */
 187                                 return(1);
 188                         }
 189                         if (sk->rqueue != NULL || sk->err != 0) 
 190                         {       /* This appears to be consistent
 191                                    with other stacks */
 192                                 return(1);
 193                         }
 194                         return(0);
 195 
 196                 case SEL_OUT:
 197                         if(sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE) 
 198                         {
 199                                 return(1);
 200                         }
 201                         if(sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
 202                         {
 203                                 return(1);
 204                         }
 205                         return(0);
 206         
 207                 case SEL_EX:
 208                         if (sk->err)
 209                                 return(1); /* Socket has gone into error state (eg icmp error) */
 210                         return(0);
 211         }
 212         return(0);
 213 }

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