xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 4927)
1 /*	uipc_syscalls.c	4.4	81/11/18	*/
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/inet.h"
16 #include "../net/inet_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_LOCAL, 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(rso, wso) == 0)
61 		goto free4;
62 	rso->so_isfilerefd = wso->so_isfilerefd = 1;
63 	return;
64 free4:
65 	wf->f_count = 0;
66 	u.u_ofile[u.u_r.r_val1] = 0;
67 free3:
68 	rf->f_count = 0;
69 	u.u_ofile[r] = 0;
70 free2:
71 	sofree(wso);
72 free:
73 	sofree(rso);
74 }
75 
76 /*
77  * Splice system call interface.
78  */
79 ssplice()
80 {
81 	register struct a {
82 		int	fd1;
83 		int	fd2;
84 	} *ap = (struct a *)u.u_ap;
85 	struct file *f1, *f2;
86 COUNT(SSPLICE);
87 
88 	f1 = getf(ap->fd1);
89 	if (f1 == NULL)
90 		return;
91 	f2 = getf(ap->fd2);
92 	if (f2 == NULL)
93 		return;
94 	if (f1 == f2) {
95 		u.u_error = EINVAL;
96 		return;
97 	}
98 	if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
99 		u.u_error = ENOTSOCK;
100 		return;
101 	}
102 	if (f1->f_count > 1 || f2->f_count > 1) {
103 		u.u_error = ETOOMANYREFS;
104 		return;
105 	}
106 	u.u_error = sosplice(f1->f_socket, f2->f_socket);
107 	if (u.u_error)
108 		return;
109 	u.u_ofile[ap->fd1] = 0;
110 	u.u_ofile[ap->fd2] = 0;
111 	f1->f_count = 0;
112 	f2->f_count = 0;
113 }
114 
115 /*
116  * Socket system call interface.  Copy sa arguments
117  * set up file descriptor and call internal socket
118  * creation routine.
119  */
120 ssocket()
121 {
122 	register struct a {
123 		int	type;
124 		struct	sockproto *asp;
125 		struct	sockaddr *asa;
126 		int	options;
127 	} *uap = (struct a *)u.u_ap;
128 	struct sockproto sp;
129 	struct sockaddr sa;
130 	struct socket *so;
131 	register struct file *fp;
132 COUNT(SSOCKET);
133 
134 	if ((fp = falloc()) == NULL)
135 		return;
136 	fp->f_flag = FSOCKET|FREAD|FWRITE;
137 	if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
138 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
139 		u.u_error = EFAULT;
140 		return;
141 	}
142 	u.u_error = socreate(&so, uap->type,
143 	    uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
144 	if (u.u_error)
145 		goto bad;
146 	fp->f_socket = so;
147 	so->so_isfilerefd = 1;
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_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  */
202 sconnect()
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;
212 COUNT(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  */
247 sdisconnect()
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;
257 COUNT(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)
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  */
291 ssend()
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;
301 COUNT(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_count = uap->count;
311 	u.u_segflg = 0;
312 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
313 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
314 		u.u_error = EFAULT;
315 		return;
316 	}
317 	u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
318 }
319 
320 /*
321  * Receive data on socket.
322  */
323 sreceive()
324 {
325 	register struct a {
326 		int	fdes;
327 		struct	sockaddr *asa;
328 		caddr_t	cbuf;
329 		u_int	count;
330 	} *uap = (struct a *)u.u_ap;
331 	register struct file *fp;
332 	struct sockaddr sa;
333 COUNT(SRECEIVE);
334 
335 	fp = getf(uap->fdes);
336 	if (fp == 0)
337 		return;
338 	if ((fp->f_flag & FSOCKET) == 0) {
339 		u.u_error = ENOTSOCK;
340 		return;
341 	}
342 	u.u_count = uap->count;
343 	u.u_segflg = 0;
344 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
345 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
346 		u.u_error = EFAULT;
347 		return;
348 	}
349 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
350 	if (u.u_error)
351 		return;
352 	if (uap->asa)
353 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
354 }
355