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