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