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 structsk_buff *skb_recv_datagram(structsock *sk, unsignedflags, intnoblock, int *err)
/* */ 51 { 52 structsk_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 returnNULL;
65 } 66
67 if(sk->err)
68 { 69 release_sock(sk);
70 *err=-sk->err;
71 sk->err=0;
72 returnNULL;
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 returnNULL;
81 } 82
83 /* User doesn't want to wait */ 84 if (noblock)
85 { 86 release_sock(sk);
87 *err=-EAGAIN;
88 returnNULL;
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 returnNULL;
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 gotorestart; /* 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 returnskb;
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 voidskb_free_datagram(structsk_buff *skb)
/* */ 149 { 150 unsignedlongflags;
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 voidskb_copy_datagram(structsk_buff *skb, intoffset, char *to, intsize)
/* */ 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 intdatagram_select(structsock *sk, intsel_type, select_table *wait)
/* */ 179 { 180 select_wait(sk->sleep, wait);
181 switch(sel_type)
182 { 183 caseSEL_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 caseSEL_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 caseSEL_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 }