xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 9d26e6c7)
1 /*	uipc_syscalls.c	4.13	82/01/13	*/
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)
189 		sleep((caddr_t)&so->so_timeo, PZERO+1);
190 	u.u_error = soaccept(so, &sa);
191 	if (u.u_error) {
192 		splx(s);
193 		return;
194 	}
195 	if (uap->asa)
196 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
197 	/* deal with new file descriptor case */
198 	/* u.u_r.r_val1 = ... */
199 	splx(s);
200 }
201 
202 /*
203  * Connect socket to foreign peer; system call
204  * interface.  Copy sa arguments and call internal routine.
205  */
206 sconnect()
207 {
208 	register struct a {
209 		int	fdes;
210 		struct	sockaddr *a;
211 	} *uap = (struct a *)u.u_ap;
212 	struct sockaddr sa;
213 	register struct file *fp;
214 	register struct socket *so;
215 	int s;
216 COUNT(SCONNECT);
217 
218 	if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
219 		u.u_error = EFAULT;
220 		return;
221 	}
222 	fp = getf(uap->fdes);
223 	if (fp == 0)
224 		return;
225 	if ((fp->f_flag & FSOCKET) == 0) {
226 		u.u_error = ENOTSOCK;
227 		return;
228 	}
229 	so = fp->f_socket;
230 	u.u_error = soconnect(so, &sa);
231 	if (u.u_error)
232 		return;
233 	s = splnet();
234 	if ((so->so_options & SO_NONBLOCKING) &&
235 	    (so->so_state & SS_ISCONNECTING)) {
236 		u.u_error = EINPROGRESS;
237 		splx(s);
238 		return;
239 	}
240 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
241 		sleep((caddr_t)&so->so_timeo, PZERO+1);
242 	u.u_error = so->so_error;
243 	so->so_error = 0;
244 	splx(s);
245 }
246 
247 /*
248  * Disconnect socket from foreign peer; system call
249  * interface.  Copy sa arguments and call internal routine.
250  */
251 sdisconnect()
252 {
253 	register struct a {
254 		int	fdes;
255 		struct	sockaddr *asa;
256 	} *uap = (struct a *)u.u_ap;
257 	struct sockaddr sa;
258 	register struct file *fp;
259 	register struct socket *so;
260 	int s;
261 COUNT(SDISCONNECT);
262 
263 	if (uap->asa &&
264 	    copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
265 		u.u_error = EFAULT;
266 		return;
267 	}
268 	fp = getf(uap->fdes);
269 	if (fp == 0)
270 		return;
271 	if ((fp->f_flag & FSOCKET) == 0) {
272 		u.u_error = ENOTSOCK;
273 		return;
274 	}
275 	so = fp->f_socket;
276 	u.u_error = sodisconnect(so, uap->asa ? &sa : 0);
277 	if (u.u_error)
278 		return;
279 	s = splnet();
280 	if ((so->so_options&SO_NONBLOCKING) && (so->so_state&SS_ISDISCONNECTING)) {
281 		u.u_error = EINPROGRESS;
282 		splx(s);
283 		return;
284 	}
285 	while ((so->so_state & SS_ISDISCONNECTING) && so->so_error == 0)
286 		sleep((caddr_t)&so->so_timeo, PZERO+1);
287 	u.u_error = so->so_error;
288 	so->so_error = 0;
289 	splx(s);
290 }
291 
292 /*
293  * Send data on socket.
294  */
295 ssend()
296 {
297 	register struct a {
298 		int	fdes;
299 		struct	sockaddr *asa;
300 		caddr_t	cbuf;
301 		unsigned count;
302 	} *uap = (struct a *)u.u_ap;
303 	register struct file *fp;
304 	struct sockaddr sa;
305 COUNT(SSEND);
306 
307 	fp = getf(uap->fdes);
308 	if (fp == 0)
309 		return;
310 	if ((fp->f_flag & FSOCKET) == 0) {
311 		u.u_error = ENOTSOCK;
312 		return;
313 	}
314 	u.u_base = uap->cbuf;
315 	u.u_count = uap->count;
316 	u.u_segflg = 0;
317 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
318 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
319 		u.u_error = EFAULT;
320 		return;
321 	}
322 	u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
323 	u.u_r.r_val1 = uap->count - u.u_count;
324 }
325 
326 /*
327  * Receive data on socket.
328  */
329 sreceive()
330 {
331 	register struct a {
332 		int	fdes;
333 		struct	sockaddr *asa;
334 		caddr_t	cbuf;
335 		u_int	count;
336 	} *uap = (struct a *)u.u_ap;
337 	register struct file *fp;
338 	struct sockaddr sa;
339 COUNT(SRECEIVE);
340 
341 	fp = getf(uap->fdes);
342 	if (fp == 0)
343 		return;
344 	if ((fp->f_flag & FSOCKET) == 0) {
345 		u.u_error = ENOTSOCK;
346 		return;
347 	}
348 	u.u_base = uap->cbuf;
349 	u.u_count = uap->count;
350 	u.u_segflg = 0;
351 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
352 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
353 		u.u_error = EFAULT;
354 		return;
355 	}
356 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
357 	if (u.u_error)
358 		return;
359 	if (uap->asa)
360 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
361 	u.u_r.r_val1 = uap->count - u.u_count;
362 }
363 
364 /*
365  * Get socket address.
366  */
367 ssocketaddr()
368 {
369 	register struct a {
370 		int	fdes;
371 		struct	sockaddr *asa;
372 	} *uap = (struct a *)u.u_ap;
373 	register struct file *fp;
374 COUNT(SSOCKETADDR);
375 
376 	fp = getf(uap->fdes);
377 	if (fp == 0)
378 		return;
379 	if ((fp->f_flag & FSOCKET) == 0) {
380 		u.u_error = ENOTSOCK;
381 		return;
382 	}
383 	if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa,
384 	    sizeof (struct sockaddr))) {
385 		u.u_error = EFAULT;
386 		return;
387 	}
388 }
389