fix to race in accept
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
62229532 1/* uipc_syscalls.c 4.18 82/06/12 */
c8c7dd0e
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/proc.h"
8#include "../h/file.h"
9#include "../h/inode.h"
10#include "../h/buf.h"
11#include "../h/mbuf.h"
c8c7dd0e
BJ
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
3b3ee18d
BJ
15#include "../net/in.h"
16#include "../net/in_systm.h"
c8c7dd0e
BJ
17
18/*
19 * Socket system call interface.
20 *
21 * These routines interface the socket routines to UNIX,
22 * isolating the system interface from the socket-protocol interface.
23 *
cc15ab5d 24 * TODO:
cc15ab5d 25 * SO_INTNOTIFY
c8c7dd0e
BJ
26 */
27
4c078bb2 28static struct sockproto localproto = { PF_UNIX, 0 };
c8c7dd0e 29/*
cc15ab5d 30 * Pipe system call interface.
c8c7dd0e 31 */
cc15ab5d 32spipe()
c8c7dd0e 33{
cc15ab5d
BJ
34 register struct file *rf, *wf;
35 struct socket *rso, *wso;
36 int r;
2b4b57cd 37COUNT(SPIPE);
cc15ab5d 38
2b4b57cd
BJ
39 u.u_error = socreate(&rso, SOCK_STREAM,
40 &localproto, (struct sockaddr *)0, 0);
cc15ab5d 41 if (u.u_error)
c8c7dd0e 42 return;
2b4b57cd
BJ
43 u.u_error = socreate(&wso, SOCK_STREAM,
44 &localproto, (struct sockaddr *)0, 0);
c8c7dd0e 45 if (u.u_error)
cc15ab5d
BJ
46 goto free;
47 rf = falloc();
48 if (rf == NULL)
49 goto free2;
50 r = u.u_r.r_val1;
51 rf->f_flag = FREAD|FSOCKET;
52 rf->f_socket = rso;
53 wf = falloc();
54 if (wf == NULL)
55 goto free3;
56 wf->f_flag = FWRITE|FSOCKET;
57 wf->f_socket = wso;
58 u.u_r.r_val2 = u.u_r.r_val1;
59 u.u_r.r_val1 = r;
225bec1b 60 if (piconnect(wso, rso) == 0)
cc15ab5d 61 goto free4;
c8c7dd0e 62 return;
cc15ab5d
BJ
63free4:
64 wf->f_count = 0;
c8c7dd0e 65 u.u_ofile[u.u_r.r_val1] = 0;
cc15ab5d
BJ
66free3:
67 rf->f_count = 0;
68 u.u_ofile[r] = 0;
69free2:
4ad99bae 70 wso->so_state |= SS_USERGONE;
cc15ab5d
BJ
71 sofree(wso);
72free:
4ad99bae 73 rso->so_state |= SS_USERGONE;
cc15ab5d 74 sofree(rso);
c8c7dd0e
BJ
75}
76
c8c7dd0e 77/*
2b4b57cd 78 * Socket system call interface. Copy sa arguments
cc15ab5d
BJ
79 * set up file descriptor and call internal socket
80 * creation routine.
c8c7dd0e 81 */
cc15ab5d 82ssocket()
c8c7dd0e 83{
cc15ab5d
BJ
84 register struct a {
85 int type;
2b4b57cd
BJ
86 struct sockproto *asp;
87 struct sockaddr *asa;
cc15ab5d
BJ
88 int options;
89 } *uap = (struct a *)u.u_ap;
2b4b57cd
BJ
90 struct sockproto sp;
91 struct sockaddr sa;
92 struct socket *so;
cc15ab5d 93 register struct file *fp;
2b4b57cd 94COUNT(SSOCKET);
c8c7dd0e 95
cc15ab5d
BJ
96 if ((fp = falloc()) == NULL)
97 return;
98 fp->f_flag = FSOCKET|FREAD|FWRITE;
2b4b57cd
BJ
99 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
100 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
101 u.u_error = EFAULT;
102 return;
c8c7dd0e 103 }
2b4b57cd
BJ
104 u.u_error = socreate(&so, uap->type,
105 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
cc15ab5d
BJ
106 if (u.u_error)
107 goto bad;
2b4b57cd 108 fp->f_socket = so;
cc15ab5d
BJ
109 return;
110bad:
111 u.u_ofile[u.u_r.r_val1] = 0;
112 fp->f_count = 0;
c8c7dd0e 113}
ae921915 114
2b4b57cd
BJ
115/*
116 * Accept system call interface.
117 */
ae921915
BJ
118saccept()
119{
2b4b57cd
BJ
120 register struct a {
121 int fdes;
122 struct sockaddr *asa;
123 } *uap = (struct a *)u.u_ap;
124 struct sockaddr sa;
125 register struct file *fp;
126 struct socket *so;
127 int s;
128COUNT(SACCEPT);
ae921915 129
2b4b57cd
BJ
130 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
131 u.u_error = EFAULT;
132 return;
133 }
134 fp = getf(uap->fdes);
135 if (fp == 0)
136 return;
137 if ((fp->f_flag & FSOCKET) == 0) {
138 u.u_error = ENOTSOCK;
139 return;
140 }
141 s = splnet();
142 so = fp->f_socket;
62364f0e 143 if ((so->so_state & SS_NBIO) &&
2b4b57cd
BJ
144 (so->so_state & SS_CONNAWAITING) == 0) {
145 u.u_error = EWOULDBLOCK;
146 splx(s);
147 return;
148 }
62229532
BJ
149 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) {
150 if (so->so_state & SS_CANTRCVMORE) {
151 so->so_error = ECONNABORTED;
152 break;
153 }
d08c5322 154 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 155 }
f269ef23
BJ
156 if (so->so_error) {
157 u.u_error = so->so_error;
158 splx(s);
159 return;
160 }
2b4b57cd
BJ
161 u.u_error = soaccept(so, &sa);
162 if (u.u_error) {
163 splx(s);
164 return;
165 }
d08c5322
BJ
166 if (uap->asa)
167 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
2b4b57cd
BJ
168 /* deal with new file descriptor case */
169 /* u.u_r.r_val1 = ... */
170 splx(s);
ae921915
BJ
171}
172
c8c7dd0e
BJ
173/*
174 * Connect socket to foreign peer; system call
2b4b57cd 175 * interface. Copy sa arguments and call internal routine.
c8c7dd0e
BJ
176 */
177sconnect()
178{
179 register struct a {
2b4b57cd
BJ
180 int fdes;
181 struct sockaddr *a;
c8c7dd0e 182 } *uap = (struct a *)u.u_ap;
2b4b57cd 183 struct sockaddr sa;
c8c7dd0e
BJ
184 register struct file *fp;
185 register struct socket *so;
186 int s;
2b4b57cd 187COUNT(SCONNECT);
c8c7dd0e 188
2b4b57cd 189 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
190 u.u_error = EFAULT;
191 return;
192 }
193 fp = getf(uap->fdes);
194 if (fp == 0)
195 return;
196 if ((fp->f_flag & FSOCKET) == 0) {
197 u.u_error = ENOTSOCK;
198 return;
199 }
200 so = fp->f_socket;
2b4b57cd 201 u.u_error = soconnect(so, &sa);
c8c7dd0e
BJ
202 if (u.u_error)
203 return;
204 s = splnet();
62364f0e 205 if ((so->so_state & SS_NBIO) &&
cc15ab5d 206 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 207 u.u_error = EINPROGRESS;
cc15ab5d 208 splx(s);
c8c7dd0e
BJ
209 return;
210 }
cc15ab5d 211 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
212 sleep((caddr_t)&so->so_timeo, PZERO+1);
213 u.u_error = so->so_error;
cc15ab5d
BJ
214 so->so_error = 0;
215 splx(s);
c8c7dd0e
BJ
216}
217
c8c7dd0e
BJ
218/*
219 * Send data on socket.
220 */
221ssend()
222{
223 register struct a {
224 int fdes;
2b4b57cd 225 struct sockaddr *asa;
c8c7dd0e 226 caddr_t cbuf;
2b4b57cd 227 unsigned count;
c8c7dd0e
BJ
228 } *uap = (struct a *)u.u_ap;
229 register struct file *fp;
2b4b57cd
BJ
230 struct sockaddr sa;
231COUNT(SSEND);
c8c7dd0e
BJ
232
233 fp = getf(uap->fdes);
234 if (fp == 0)
235 return;
236 if ((fp->f_flag & FSOCKET) == 0) {
237 u.u_error = ENOTSOCK;
238 return;
239 }
d6e7dc87 240 u.u_base = uap->cbuf;
c8c7dd0e
BJ
241 u.u_count = uap->count;
242 u.u_segflg = 0;
cc15ab5d 243 if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
2b4b57cd 244 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
245 u.u_error = EFAULT;
246 return;
247 }
2b4b57cd 248 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
d6e7dc87 249 u.u_r.r_val1 = uap->count - u.u_count;
c8c7dd0e
BJ
250}
251
cc15ab5d
BJ
252/*
253 * Receive data on socket.
254 */
255sreceive()
256{
257 register struct a {
258 int fdes;
2b4b57cd 259 struct sockaddr *asa;
cc15ab5d 260 caddr_t cbuf;
ae921915 261 u_int count;
cc15ab5d
BJ
262 } *uap = (struct a *)u.u_ap;
263 register struct file *fp;
2b4b57cd
BJ
264 struct sockaddr sa;
265COUNT(SRECEIVE);
cc15ab5d
BJ
266
267 fp = getf(uap->fdes);
268 if (fp == 0)
269 return;
270 if ((fp->f_flag & FSOCKET) == 0) {
271 u.u_error = ENOTSOCK;
272 return;
273 }
d6e7dc87 274 u.u_base = uap->cbuf;
cc15ab5d
BJ
275 u.u_count = uap->count;
276 u.u_segflg = 0;
277 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
2b4b57cd 278 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
279 u.u_error = EFAULT;
280 return;
281 }
2b4b57cd
BJ
282 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
283 if (u.u_error)
284 return;
285 if (uap->asa)
286 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
d6e7dc87 287 u.u_r.r_val1 = uap->count - u.u_count;
cc15ab5d 288}
a3076b07
BJ
289
290/*
291 * Get socket address.
292 */
293ssocketaddr()
294{
295 register struct a {
296 int fdes;
297 struct sockaddr *asa;
298 } *uap = (struct a *)u.u_ap;
299 register struct file *fp;
05d69517
SL
300 register struct socket *so;
301 struct sockaddr addr;
a3076b07
BJ
302COUNT(SSOCKETADDR);
303
304 fp = getf(uap->fdes);
305 if (fp == 0)
306 return;
307 if ((fp->f_flag & FSOCKET) == 0) {
308 u.u_error = ENOTSOCK;
309 return;
310 }
05d69517
SL
311 so = fp->f_socket;
312 u.u_error =
313 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
314 if (u.u_error)
2752c877 315 return;
05d69517
SL
316 if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
317 u.u_error = EFAULT;
2752c877 318}