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