set u.u_base
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
... / ...
CommitLineData
1/* uipc_syscalls.c 4.11 81/12/09 */
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"
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
15#include "../net/in.h"
16#include "../net/in_systm.h"
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 *
24 * TODO:
25 * SO_INTNOTIFY
26 */
27
28static struct sockproto localproto = { PF_UNIX, 0 };
29/*
30 * Pipe system call interface.
31 */
32spipe()
33{
34 register struct file *rf, *wf;
35 struct socket *rso, *wso;
36 int r;
37COUNT(SPIPE);
38
39 u.u_error = socreate(&rso, SOCK_STREAM,
40 &localproto, (struct sockaddr *)0, 0);
41 if (u.u_error)
42 return;
43 u.u_error = socreate(&wso, SOCK_STREAM,
44 &localproto, (struct sockaddr *)0, 0);
45 if (u.u_error)
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;
60 if (piconnect(wso, rso) == 0)
61 goto free4;
62 return;
63free4:
64 wf->f_count = 0;
65 u.u_ofile[u.u_r.r_val1] = 0;
66free3:
67 rf->f_count = 0;
68 u.u_ofile[r] = 0;
69free2:
70 wso->so_state |= SS_USERGONE;
71 sofree(wso);
72free:
73 rso->so_state |= SS_USERGONE;
74 sofree(rso);
75}
76
77/*
78 * Splice system call interface.
79 */
80ssplice()
81{
82 register struct a {
83 int fd1;
84 int fd2;
85 } *ap = (struct a *)u.u_ap;
86 struct file *f1, *f2;
87COUNT(SSPLICE);
88
89 f1 = getf(ap->fd1);
90 if (f1 == NULL)
91 return;
92 f2 = getf(ap->fd2);
93 if (f2 == NULL)
94 return;
95 if (f1 == f2) {
96 u.u_error = EINVAL;
97 return;
98 }
99 if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
100 u.u_error = ENOTSOCK;
101 return;
102 }
103 if (f1->f_count > 1 || f2->f_count > 1) {
104 u.u_error = ETOOMANYREFS;
105 return;
106 }
107 u.u_error = sosplice(f1->f_socket, f2->f_socket);
108 if (u.u_error)
109 return;
110 u.u_ofile[ap->fd1] = 0;
111 u.u_ofile[ap->fd2] = 0;
112 f1->f_count = 0;
113 f2->f_count = 0;
114}
115
116/*
117 * Socket system call interface. Copy sa arguments
118 * set up file descriptor and call internal socket
119 * creation routine.
120 */
121ssocket()
122{
123 register struct a {
124 int type;
125 struct sockproto *asp;
126 struct sockaddr *asa;
127 int options;
128 } *uap = (struct a *)u.u_ap;
129 struct sockproto sp;
130 struct sockaddr sa;
131 struct socket *so;
132 register struct file *fp;
133COUNT(SSOCKET);
134
135 if ((fp = falloc()) == NULL)
136 return;
137 fp->f_flag = FSOCKET|FREAD|FWRITE;
138 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
139 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
140 u.u_error = EFAULT;
141 return;
142 }
143 u.u_error = socreate(&so, uap->type,
144 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
145 if (u.u_error)
146 goto bad;
147 fp->f_socket = so;
148 return;
149bad:
150 u.u_ofile[u.u_r.r_val1] = 0;
151 fp->f_count = 0;
152}
153
154/*
155 * Accept system call interface.
156 */
157saccept()
158{
159 register struct a {
160 int fdes;
161 struct sockaddr *asa;
162 } *uap = (struct a *)u.u_ap;
163 struct sockaddr sa;
164 register struct file *fp;
165 struct socket *so;
166 int s;
167COUNT(SACCEPT);
168
169 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
170 u.u_error = EFAULT;
171 return;
172 }
173 fp = getf(uap->fdes);
174 if (fp == 0)
175 return;
176 if ((fp->f_flag & FSOCKET) == 0) {
177 u.u_error = ENOTSOCK;
178 return;
179 }
180 s = splnet();
181 so = fp->f_socket;
182 if ((so->so_options & SO_NBIO) &&
183 (so->so_state & SS_CONNAWAITING) == 0) {
184 u.u_error = EWOULDBLOCK;
185 splx(s);
186 return;
187 }
188 u.u_error = soaccept(so, &sa);
189 if (u.u_error) {
190 splx(s);
191 return;
192 }
193 /* deal with new file descriptor case */
194 /* u.u_r.r_val1 = ... */
195 splx(s);
196}
197
198/*
199 * Connect socket to foreign peer; system call
200 * interface. Copy sa arguments and call internal routine.
201 */
202sconnect()
203{
204 register struct a {
205 int fdes;
206 struct sockaddr *a;
207 } *uap = (struct a *)u.u_ap;
208 struct sockaddr sa;
209 register struct file *fp;
210 register struct socket *so;
211 int s;
212COUNT(SCONNECT);
213
214 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
215 u.u_error = EFAULT;
216 return;
217 }
218 fp = getf(uap->fdes);
219 if (fp == 0)
220 return;
221 if ((fp->f_flag & FSOCKET) == 0) {
222 u.u_error = ENOTSOCK;
223 return;
224 }
225 so = fp->f_socket;
226 u.u_error = soconnect(so, &sa);
227 if (u.u_error)
228 return;
229 s = splnet();
230 if ((so->so_options & SO_NBIO) &&
231 (so->so_state & SS_ISCONNECTING)) {
232 u.u_error = EINPROGRESS;
233 splx(s);
234 return;
235 }
236 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
237 sleep((caddr_t)&so->so_timeo, PZERO+1);
238 u.u_error = so->so_error;
239 so->so_error = 0;
240 splx(s);
241}
242
243/*
244 * Disconnect socket from foreign peer; system call
245 * interface. Copy sa arguments and call internal routine.
246 */
247sdisconnect()
248{
249 register struct a {
250 int fdes;
251 struct sockaddr *asa;
252 } *uap = (struct a *)u.u_ap;
253 struct sockaddr sa;
254 register struct file *fp;
255 register struct socket *so;
256 int s;
257COUNT(SDISCONNECT);
258
259 if (uap->asa &&
260 copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
261 u.u_error = EFAULT;
262 return;
263 }
264 fp = getf(uap->fdes);
265 if (fp == 0)
266 return;
267 if ((fp->f_flag & FSOCKET) == 0) {
268 u.u_error = ENOTSOCK;
269 return;
270 }
271 so = fp->f_socket;
272 u.u_error = sodisconnect(so, uap->asa ? &sa : 0);
273 if (u.u_error)
274 return;
275 s = splnet();
276 if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) {
277 u.u_error = EINPROGRESS;
278 splx(s);
279 return;
280 }
281 while ((so->so_state & SS_ISDISCONNECTING) && so->so_error == 0)
282 sleep((caddr_t)&so->so_timeo, PZERO+1);
283 u.u_error = so->so_error;
284 so->so_error = 0;
285 splx(s);
286}
287
288/*
289 * Send data on socket.
290 */
291ssend()
292{
293 register struct a {
294 int fdes;
295 struct sockaddr *asa;
296 caddr_t cbuf;
297 unsigned count;
298 } *uap = (struct a *)u.u_ap;
299 register struct file *fp;
300 struct sockaddr sa;
301COUNT(SSEND);
302
303 fp = getf(uap->fdes);
304 if (fp == 0)
305 return;
306 if ((fp->f_flag & FSOCKET) == 0) {
307 u.u_error = ENOTSOCK;
308 return;
309 }
310 u.u_base = uap->cbuf;
311 u.u_count = uap->count;
312 u.u_segflg = 0;
313 if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
314 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
315 u.u_error = EFAULT;
316 return;
317 }
318 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
319 u.u_r.r_val1 = uap->count - u.u_count;
320}
321
322/*
323 * Receive data on socket.
324 */
325sreceive()
326{
327 register struct a {
328 int fdes;
329 struct sockaddr *asa;
330 caddr_t cbuf;
331 u_int count;
332 } *uap = (struct a *)u.u_ap;
333 register struct file *fp;
334 struct sockaddr sa;
335COUNT(SRECEIVE);
336
337 fp = getf(uap->fdes);
338 if (fp == 0)
339 return;
340 if ((fp->f_flag & FSOCKET) == 0) {
341 u.u_error = ENOTSOCK;
342 return;
343 }
344 u.u_base = uap->cbuf;
345 u.u_count = uap->count;
346 u.u_segflg = 0;
347 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
348 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
349 u.u_error = EFAULT;
350 return;
351 }
352 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
353 if (u.u_error)
354 return;
355 if (uap->asa)
356 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
357 u.u_r.r_val1 = uap->count - u.u_count;
358}
359
360/*
361 * Get socket address.
362 */
363ssocketaddr()
364{
365 register struct a {
366 int fdes;
367 struct sockaddr *asa;
368 } *uap = (struct a *)u.u_ap;
369 register struct file *fp;
370COUNT(SSOCKETADDR);
371
372 fp = getf(uap->fdes);
373 if (fp == 0)
374 return;
375 if ((fp->f_flag & FSOCKET) == 0) {
376 u.u_error = ENOTSOCK;
377 return;
378 }
379 if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa,
380 sizeof (struct sockaddr))) {
381 u.u_error = EFAULT;
382 return;
383 }
384}