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