xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 0b685140)
1 /*	uipc_syscalls.c	4.14	82/02/25	*/
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 
28 static	struct sockproto localproto = { PF_UNIX, 0 };
29 /*
30  * Pipe system call interface.
31  */
32 spipe()
33 {
34 	register struct file *rf, *wf;
35 	struct socket *rso, *wso;
36 	int r;
37 COUNT(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;
63 free4:
64 	wf->f_count = 0;
65 	u.u_ofile[u.u_r.r_val1] = 0;
66 free3:
67 	rf->f_count = 0;
68 	u.u_ofile[r] = 0;
69 free2:
70 	wso->so_state |= SS_USERGONE;
71 	sofree(wso);
72 free:
73 	rso->so_state |= SS_USERGONE;
74 	sofree(rso);
75 }
76 
77 /*
78  * Splice system call interface.
79  */
80 ssplice()
81 {
82 	register struct a {
83 		int	fd1;
84 		int	fd2;
85 	} *ap = (struct a *)u.u_ap;
86 	struct file *f1, *f2;
87 COUNT(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  */
121 ssocket()
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;
133 COUNT(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;
149 bad:
150 	u.u_ofile[u.u_r.r_val1] = 0;
151 	fp->f_count = 0;
152 }
153 
154 /*
155  * Accept system call interface.
156  */
157 saccept()
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;
167 COUNT(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_NONBLOCKING) &&
183 	    (so->so_state & SS_CONNAWAITING) == 0) {
184 		u.u_error = EWOULDBLOCK;
185 		splx(s);
186 		return;
187 	}
188 	while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0)
189 		sleep((caddr_t)&so->so_timeo, PZERO+1);
190 	if (so->so_error) {
191 		u.u_error = so->so_error;
192 		splx(s);
193 		return;
194 	}
195 	u.u_error = soaccept(so, &sa);
196 	if (u.u_error) {
197 		splx(s);
198 		return;
199 	}
200 	if (uap->asa)
201 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
202 	/* deal with new file descriptor case */
203 	/* u.u_r.r_val1 = ... */
204 	splx(s);
205 }
206 
207 /*
208  * Connect socket to foreign peer; system call
209  * interface.  Copy sa arguments and call internal routine.
210  */
211 sconnect()
212 {
213 	register struct a {
214 		int	fdes;
215 		struct	sockaddr *a;
216 	} *uap = (struct a *)u.u_ap;
217 	struct sockaddr sa;
218 	register struct file *fp;
219 	register struct socket *so;
220 	int s;
221 COUNT(SCONNECT);
222 
223 	if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
224 		u.u_error = EFAULT;
225 		return;
226 	}
227 	fp = getf(uap->fdes);
228 	if (fp == 0)
229 		return;
230 	if ((fp->f_flag & FSOCKET) == 0) {
231 		u.u_error = ENOTSOCK;
232 		return;
233 	}
234 	so = fp->f_socket;
235 	u.u_error = soconnect(so, &sa);
236 	if (u.u_error)
237 		return;
238 	s = splnet();
239 	if ((so->so_options & SO_NONBLOCKING) &&
240 	    (so->so_state & SS_ISCONNECTING)) {
241 		u.u_error = EINPROGRESS;
242 		splx(s);
243 		return;
244 	}
245 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
246 		sleep((caddr_t)&so->so_timeo, PZERO+1);
247 	u.u_error = so->so_error;
248 	so->so_error = 0;
249 	splx(s);
250 }
251 
252 /*
253  * Disconnect socket from foreign peer; system call
254  * interface.  Copy sa arguments and call internal routine.
255  */
256 sdisconnect()
257 {
258 	register struct a {
259 		int	fdes;
260 		struct	sockaddr *asa;
261 	} *uap = (struct a *)u.u_ap;
262 	struct sockaddr sa;
263 	register struct file *fp;
264 	register struct socket *so;
265 	int s;
266 COUNT(SDISCONNECT);
267 
268 	if (uap->asa &&
269 	    copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
270 		u.u_error = EFAULT;
271 		return;
272 	}
273 	fp = getf(uap->fdes);
274 	if (fp == 0)
275 		return;
276 	if ((fp->f_flag & FSOCKET) == 0) {
277 		u.u_error = ENOTSOCK;
278 		return;
279 	}
280 	so = fp->f_socket;
281 	u.u_error = sodisconnect(so, uap->asa ? &sa : 0);
282 	if (u.u_error)
283 		return;
284 	s = splnet();
285 	if ((so->so_options&SO_NONBLOCKING) && (so->so_state&SS_ISDISCONNECTING)) {
286 		u.u_error = EINPROGRESS;
287 		splx(s);
288 		return;
289 	}
290 	while ((so->so_state & SS_ISDISCONNECTING) && so->so_error == 0)
291 		sleep((caddr_t)&so->so_timeo, PZERO+1);
292 	u.u_error = so->so_error;
293 	so->so_error = 0;
294 	splx(s);
295 }
296 
297 /*
298  * Send data on socket.
299  */
300 ssend()
301 {
302 	register struct a {
303 		int	fdes;
304 		struct	sockaddr *asa;
305 		caddr_t	cbuf;
306 		unsigned count;
307 	} *uap = (struct a *)u.u_ap;
308 	register struct file *fp;
309 	struct sockaddr sa;
310 COUNT(SSEND);
311 
312 	fp = getf(uap->fdes);
313 	if (fp == 0)
314 		return;
315 	if ((fp->f_flag & FSOCKET) == 0) {
316 		u.u_error = ENOTSOCK;
317 		return;
318 	}
319 	u.u_base = uap->cbuf;
320 	u.u_count = uap->count;
321 	u.u_segflg = 0;
322 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
323 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
324 		u.u_error = EFAULT;
325 		return;
326 	}
327 	u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
328 	u.u_r.r_val1 = uap->count - u.u_count;
329 }
330 
331 /*
332  * Receive data on socket.
333  */
334 sreceive()
335 {
336 	register struct a {
337 		int	fdes;
338 		struct	sockaddr *asa;
339 		caddr_t	cbuf;
340 		u_int	count;
341 	} *uap = (struct a *)u.u_ap;
342 	register struct file *fp;
343 	struct sockaddr sa;
344 COUNT(SRECEIVE);
345 
346 	fp = getf(uap->fdes);
347 	if (fp == 0)
348 		return;
349 	if ((fp->f_flag & FSOCKET) == 0) {
350 		u.u_error = ENOTSOCK;
351 		return;
352 	}
353 	u.u_base = uap->cbuf;
354 	u.u_count = uap->count;
355 	u.u_segflg = 0;
356 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
357 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
358 		u.u_error = EFAULT;
359 		return;
360 	}
361 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
362 	if (u.u_error)
363 		return;
364 	if (uap->asa)
365 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
366 	u.u_r.r_val1 = uap->count - u.u_count;
367 }
368 
369 /*
370  * Get socket address.
371  */
372 ssocketaddr()
373 {
374 	register struct a {
375 		int	fdes;
376 		struct	sockaddr *asa;
377 	} *uap = (struct a *)u.u_ap;
378 	register struct file *fp;
379 COUNT(SSOCKETADDR);
380 
381 	fp = getf(uap->fdes);
382 	if (fp == 0)
383 		return;
384 	if ((fp->f_flag & FSOCKET) == 0) {
385 		u.u_error = ENOTSOCK;
386 		return;
387 	}
388 	if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa,
389 	    sizeof (struct sockaddr))) {
390 		u.u_error = EFAULT;
391 		return;
392 	}
393 }
394