~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/core/datagram.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 poll code and mostly
  7  *      identical recvmsg() code. So we share it here. The poll was shared before but buried in udp.c so I moved it.
  8  *
  9  *      Authors:        Alan Cox <alan@redhat.com>. (datagram_poll() 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 poll 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  *              Darryl Miles    :       Fixed non-blocking SOCK_STREAM.
 22  *              Alan Cox        :       POSIXisms
 23  *              Pete Wyckoff    :       Unconnected accept() fix.
 24  *
 25  */
 26 
 27 #include <linux/types.h>
 28 #include <linux/kernel.h>
 29 #include <asm/uaccess.h>
 30 #include <asm/system.h>
 31 #include <linux/mm.h>
 32 #include <linux/interrupt.h>
 33 #include <linux/in.h>
 34 #include <linux/errno.h>
 35 #include <linux/sched.h>
 36 #include <linux/inet.h>
 37 #include <linux/netdevice.h>
 38 #include <linux/poll.h>
 39 
 40 #include <net/ip.h>
 41 #include <net/protocol.h>
 42 #include <net/route.h>
 43 #include <net/tcp.h>
 44 #include <net/udp.h>
 45 #include <linux/skbuff.h>
 46 #include <net/sock.h>
 47 
 48 
 49 /*
 50  *      Is a socket 'connection oriented' ?
 51  */
 52  
 53 static inline int connection_based(struct sock *sk)
 54 {
 55         return (sk->type==SOCK_SEQPACKET || sk->type==SOCK_STREAM);
 56 }
 57 
 58 
 59 /*
 60  * Wait for a packet..
 61  */
 62 
 63 static int wait_for_packet(struct sock * sk, int *err, long *timeo_p)
 64 {
 65         int error;
 66 
 67         DECLARE_WAITQUEUE(wait, current);
 68 
 69         __set_current_state(TASK_INTERRUPTIBLE);
 70         add_wait_queue_exclusive(sk->sleep, &wait);
 71 
 72         /* Socket errors? */
 73         error = sock_error(sk);
 74         if (error)
 75                 goto out;
 76 
 77         if (!skb_queue_empty(&sk->receive_queue))
 78                 goto ready;
 79 
 80         /* Socket shut down? */
 81         if (sk->shutdown & RCV_SHUTDOWN)
 82                 goto out;
 83 
 84         /* Sequenced packets can come disconnected. If so we report the problem */
 85         error = -ENOTCONN;
 86         if(connection_based(sk) && !(sk->state==TCP_ESTABLISHED || sk->state==TCP_LISTEN))
 87                 goto out;
 88 
 89         /* handle signals */
 90         if (signal_pending(current))
 91                 goto interrupted;
 92 
 93         *timeo_p = schedule_timeout(*timeo_p);
 94 
 95 ready:
 96         current->state = TASK_RUNNING;
 97         remove_wait_queue(sk->sleep, &wait);
 98         return 0;
 99 
100 interrupted:
101         error = sock_intr_errno(*timeo_p);
102 out:
103         current->state = TASK_RUNNING;
104         remove_wait_queue(sk->sleep, &wait);
105         *err = error;
106         return error;
107 }
108 
109 /*
110  *      Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
111  *      races. This replaces identical code in packet,raw and udp, as well as the IPX
112  *      AX.25 and Appletalk. It also finally fixes the long standing peek and read
113  *      race for datagram sockets. If you alter this routine remember it must be
114  *      re-entrant.
115  *
116  *      This function will lock the socket if a skb is returned, so the caller
117  *      needs to unlock the socket in that case (usually by calling skb_free_datagram)
118  *
119  *      * It does not lock socket since today. This function is
120  *      * free of race conditions. This measure should/can improve
121  *      * significantly datagram socket latencies at high loads,
122  *      * when data copying to user space takes lots of time.
123  *      * (BTW I've just killed the last cli() in IP/IPv6/core/netlink/packet
124  *      *  8) Great win.)
125  *      *                                           --ANK (980729)
126  *
127  *      The order of the tests when we find no data waiting are specified
128  *      quite explicitly by POSIX 1003.1g, don't change them without having
129  *      the standard around please.
130  */
131 
132 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
133 {
134         int error;
135         struct sk_buff *skb;
136         long timeo;
137 
138         /* Caller is allowed not to check sk->err before skb_recv_datagram() */
139         error = sock_error(sk);
140         if (error)
141                 goto no_packet;
142 
143         timeo = sock_rcvtimeo(sk, noblock);
144 
145         do {
146                 /* Again only user level code calls this function, so nothing interrupt level
147                    will suddenly eat the receive_queue.
148 
149                    Look at current nfs client by the way...
150                    However, this function was corrent in any case. 8)
151                  */
152                 if (flags & MSG_PEEK)
153                 {
154                         unsigned long cpu_flags;
155 
156                         spin_lock_irqsave(&sk->receive_queue.lock, cpu_flags);
157                         skb = skb_peek(&sk->receive_queue);
158                         if(skb!=NULL)
159                                 atomic_inc(&skb->users);
160                         spin_unlock_irqrestore(&sk->receive_queue.lock, cpu_flags);
161                 } else
162                         skb = skb_dequeue(&sk->receive_queue);
163 
164                 if (skb)
165                         return skb;
166 
167                 /* User doesn't want to wait */
168                 error = -EAGAIN;
169                 if (!timeo)
170                         goto no_packet;
171 
172         } while (wait_for_packet(sk, err, &timeo) == 0);
173 
174         return NULL;
175 
176 no_packet:
177         *err = error;
178         return NULL;
179 }
180 
181 void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
182 {
183         kfree_skb(skb);
184 }
185 
186 /*
187  *      Copy a datagram to a linear buffer.
188  */
189 
190 int skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
191 {
192         int err = -EFAULT;
193 
194         if (!copy_to_user(to, skb->h.raw + offset, size))
195                 err = 0;
196         return err;
197 }
198 
199 
200 /*
201  *      Copy a datagram to an iovec.
202  *      Note: the iovec is modified during the copy.
203  */
204  
205 int skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to,
206                             int size)
207 {
208         return memcpy_toiovec(to, skb->h.raw + offset, size);
209 }
210 
211 /*
212  *      Datagram poll: Again totally generic. This also handles
213  *      sequenced packet sockets providing the socket receive queue
214  *      is only ever holding data ready to receive.
215  *
216  *      Note: when you _don't_ use this routine for this protocol,
217  *      and you use a different write policy from sock_writeable()
218  *      then please supply your own write_space callback.
219  */
220 
221 unsigned int datagram_poll(struct file * file, struct socket *sock, poll_table *wait)
222 {
223         struct sock *sk = sock->sk;
224         unsigned int mask;
225 
226         poll_wait(file, sk->sleep, wait);
227         mask = 0;
228 
229         /* exceptional events? */
230         if (sk->err || !skb_queue_empty(&sk->error_queue))
231                 mask |= POLLERR;
232         if (sk->shutdown == SHUTDOWN_MASK)
233                 mask |= POLLHUP;
234 
235         /* readable? */
236         if (!skb_queue_empty(&sk->receive_queue) || (sk->shutdown&RCV_SHUTDOWN))
237                 mask |= POLLIN | POLLRDNORM;
238 
239         /* Connection-based need to check for termination and startup */
240         if (connection_based(sk)) {
241                 if (sk->state==TCP_CLOSE)
242                         mask |= POLLHUP;
243                 /* connection hasn't started yet? */
244                 if (sk->state == TCP_SYN_SENT)
245                         return mask;
246         }
247 
248         /* writable? */
249         if (sock_writeable(sk))
250                 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
251         else
252                 set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
253 
254         return mask;
255 }
256 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.