?? datagram.c
字號:
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 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
50 {
51 struct sk_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 return NULL;
64 }
65
66 if(sk->err)
67 {
68 release_sock(sk);
69 *err=-sk->err;
70 sk->err=0;
71 return NULL;
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 return NULL;
80 }
81
82 /* User doesn't want to wait */
83 if (noblock)
84 {
85 release_sock(sk);
86 *err=-EAGAIN;
87 return NULL;
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 return NULL;
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 goto restart; /* 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 return skb;
138 }
139
140 void skb_free_datagram(struct sk_buff *skb)
141 {
142 unsigned long flags;
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 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
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 int datagram_select(struct sock *sk, int sel_type, select_table *wait)
171 {
172 select_wait(sk->sleep, wait);
173 switch(sel_type)
174 {
175 case SEL_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 case SEL_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 case SEL_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 }
206
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -