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