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