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