xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 7501)
1 /*	uipc_syscalls.c	4.21	82/07/24	*/
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 #include "../h/descrip.h"
18 
19 ssocreate()
20 {
21 
22 }
23 
24 ssobind()
25 {
26 
27 }
28 
29 ssolisten()
30 {
31 
32 }
33 
34 ssoaccept()
35 {
36 
37 }
38 
39 ssoconnect()
40 {
41 
42 }
43 
44 ssocreatepair()
45 {
46 
47 }
48 
49 ssosendto()
50 {
51 
52 }
53 
54 ssosend()
55 {
56 
57 }
58 
59 ssorecvfrom()
60 {
61 
62 }
63 
64 ssorecv()
65 {
66 
67 }
68 
69 ssosendm()
70 {
71 
72 }
73 
74 ssorecvm()
75 {
76 
77 }
78 
79 ssoshutdown()
80 {
81 
82 }
83 
84 /*
85  * Socket system call interface.
86  *
87  * These routines interface the socket routines to UNIX,
88  * isolating the system interface from the socket-protocol interface.
89  *
90  * TODO:
91  *	SO_INTNOTIFY
92  */
93 
94 static	struct sockproto localproto = { PF_UNIX, 0 };
95 /*
96  * Pipe system call interface.
97  */
98 spipe()
99 {
100 	register struct file *rf, *wf;
101 	struct socket *rso, *wso;
102 	int r;
103 
104 	u.u_error = socreate(&rso, SOCK_STREAM,
105 	    &localproto, (struct sockaddr *)0, 0);
106 	if (u.u_error)
107 		return;
108 	u.u_error = socreate(&wso, SOCK_STREAM,
109 	    &localproto, (struct sockaddr *)0, 0);
110 	if (u.u_error)
111 		goto free;
112 	rf = falloc();
113 	if (rf == NULL)
114 		goto free2;
115 	r = u.u_r.r_val1;
116 	rf->f_flag = FREAD;
117 	rf->f_type = DTYPE_SOCKET;
118 	rf->f_socket = rso;
119 	wf = falloc();
120 	if (wf == NULL)
121 		goto free3;
122 	wf->f_flag = FWRITE;
123 	wf->f_type = DTYPE_SOCKET;
124 	wf->f_socket = wso;
125 	u.u_r.r_val2 = u.u_r.r_val1;
126 	u.u_r.r_val1 = r;
127 	if (piconnect(wso, rso) == 0)
128 		goto free4;
129 	return;
130 free4:
131 	wf->f_count = 0;
132 	u.u_ofile[u.u_r.r_val2] = 0;
133 free3:
134 	rf->f_count = 0;
135 	u.u_ofile[r] = 0;
136 free2:
137 	wso->so_state |= SS_NOFDREF;
138 	sofree(wso);
139 free:
140 	rso->so_state |= SS_NOFDREF;
141 	sofree(rso);
142 }
143 
144 /*
145  * Socket system call interface.  Copy sa arguments
146  * set up file descriptor and call internal socket
147  * creation routine.
148  */
149 ssocket()
150 {
151 	register struct a {
152 		int	type;
153 		struct	sockproto *asp;
154 		struct	sockaddr *asa;
155 		int	options;
156 	} *uap = (struct a *)u.u_ap;
157 	struct sockproto sp;
158 	struct sockaddr sa;
159 	struct socket *so;
160 	register struct file *fp;
161 
162 	if ((fp = falloc()) == NULL)
163 		return;
164 	fp->f_flag = FREAD|FWRITE;
165 	fp->f_type = DTYPE_SOCKET;
166 	if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
167 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
168 		u.u_error = EFAULT;
169 		return;
170 	}
171 	u.u_error = socreate(&so, uap->type,
172 	    uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
173 	if (u.u_error)
174 		goto bad;
175 	fp->f_socket = so;
176 	return;
177 bad:
178 	u.u_ofile[u.u_r.r_val1] = 0;
179 	fp->f_count = 0;
180 }
181 
182 /*
183  * Accept system call interface.
184  */
185 saccept()
186 {
187 	register struct a {
188 		int	fdes;
189 		struct	sockaddr *asa;
190 	} *uap = (struct a *)u.u_ap;
191 	struct sockaddr sa;
192 	register struct file *fp;
193 	struct socket *so;
194 	int s;
195 
196 	if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
197 		u.u_error = EFAULT;
198 		return;
199 	}
200 	fp = getf(uap->fdes);
201 	if (fp == 0)
202 		return;
203 	if (fp->f_type != DTYPE_SOCKET) {
204 		u.u_error = ENOTSOCK;
205 		return;
206 	}
207 	s = splnet();
208 	so = fp->f_socket;
209 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
210 		u.u_error = EINVAL;
211 		splx(s);
212 		return;
213 	}
214 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
215 		u.u_error = EWOULDBLOCK;
216 		splx(s);
217 		return;
218 	}
219 	while (so->so_qlen == 0 && so->so_error == 0) {
220 		if (so->so_state & SS_CANTRCVMORE) {
221 			so->so_error = ECONNABORTED;
222 			break;
223 		}
224 		sleep((caddr_t)&so->so_timeo, PZERO+1);
225 	}
226 	if (so->so_error) {
227 		u.u_error = so->so_error;
228 		splx(s);
229 		return;
230 	}
231 	if ((so->so_options & SO_NEWFDONCONN) == 0) {
232 		struct socket *nso = so->so_q;
233 		(void) soqremque(nso, 1);
234 		soclose(so, 1);
235 		fp->f_socket = nso;
236 		nso->so_q = 0;
237 		so = nso;
238 		goto ret;
239 	}
240 	if (ufalloc() < 0) {
241 		splx(s);
242 		return;
243 	}
244 	fp = falloc();
245 	if (fp == 0) {
246 		u.u_ofile[u.u_r.r_val1] = 0;
247 		splx(s);
248 		return;
249 	}
250 	fp->f_type = DTYPE_SOCKET;
251 	fp->f_flag = FREAD|FWRITE;
252 	fp->f_socket = so->so_q;
253 	so->so_q = so->so_q->so_q;
254 	so->so_qlen--;
255 ret:
256 	soaccept(so, &sa);
257 	if (uap->asa)
258 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
259 	splx(s);
260 }
261 
262 /*
263  * Connect socket to foreign peer; system call
264  * interface.  Copy sa arguments and call internal routine.
265  */
266 sconnect()
267 {
268 	register struct a {
269 		int	fdes;
270 		struct	sockaddr *a;
271 	} *uap = (struct a *)u.u_ap;
272 	struct sockaddr sa;
273 	register struct file *fp;
274 	register struct socket *so;
275 	int s;
276 
277 	if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
278 		u.u_error = EFAULT;
279 		return;
280 	}
281 	fp = getf(uap->fdes);
282 	if (fp == 0)
283 		return;
284 	if (fp->f_type != DTYPE_SOCKET) {
285 		u.u_error = ENOTSOCK;
286 		return;
287 	}
288 	so = fp->f_socket;
289 	u.u_error = soconnect(so, &sa);
290 	if (u.u_error)
291 		return;
292 	s = splnet();
293 	if ((so->so_state & SS_NBIO) &&
294 	    (so->so_state & SS_ISCONNECTING)) {
295 		u.u_error = EINPROGRESS;
296 		splx(s);
297 		return;
298 	}
299 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
300 		sleep((caddr_t)&so->so_timeo, PZERO+1);
301 	u.u_error = so->so_error;
302 	so->so_error = 0;
303 	splx(s);
304 }
305 
306 /*
307  * Send data on socket.
308  */
309 ssend()
310 {
311 	register struct a {
312 		int	fdes;
313 		struct	sockaddr *asa;
314 		caddr_t	cbuf;
315 		unsigned count;
316 	} *uap = (struct a *)u.u_ap;
317 	register struct file *fp;
318 	struct sockaddr sa;
319 
320 	fp = getf(uap->fdes);
321 	if (fp == 0)
322 		return;
323 	if (fp->f_type != DTYPE_SOCKET) {
324 		u.u_error = ENOTSOCK;
325 		return;
326 	}
327 	u.u_base = uap->cbuf;
328 	u.u_count = uap->count;
329 	u.u_segflg = 0;
330 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
331 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
332 		u.u_error = EFAULT;
333 		return;
334 	}
335 	u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
336 	u.u_r.r_val1 = uap->count - u.u_count;
337 }
338 
339 /*
340  * Receive data on socket.
341  */
342 sreceive()
343 {
344 	register struct a {
345 		int	fdes;
346 		struct	sockaddr *asa;
347 		caddr_t	cbuf;
348 		u_int	count;
349 	} *uap = (struct a *)u.u_ap;
350 	register struct file *fp;
351 	struct sockaddr sa;
352 
353 	fp = getf(uap->fdes);
354 	if (fp == 0)
355 		return;
356 	if (fp->f_type != DTYPE_SOCKET) {
357 		u.u_error = ENOTSOCK;
358 		return;
359 	}
360 	u.u_base = uap->cbuf;
361 	u.u_count = uap->count;
362 	u.u_segflg = 0;
363 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
364 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
365 		u.u_error = EFAULT;
366 		return;
367 	}
368 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
369 	if (u.u_error)
370 		return;
371 	if (uap->asa)
372 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
373 	u.u_r.r_val1 = uap->count - u.u_count;
374 }
375 
376 /*
377  * Get socket address.
378  */
379 ssocketaddr()
380 {
381 	register struct a {
382 		int	fdes;
383 		struct	sockaddr *asa;
384 	} *uap = (struct a *)u.u_ap;
385 	register struct file *fp;
386 	register struct socket *so;
387 	struct sockaddr addr;
388 
389 	fp = getf(uap->fdes);
390 	if (fp == 0)
391 		return;
392 	if (fp->f_type != DTYPE_SOCKET) {
393 		u.u_error = ENOTSOCK;
394 		return;
395 	}
396 	so = fp->f_socket;
397 	u.u_error =
398 		(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
399 	if (u.u_error)
400 		return;
401 	if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
402 		u.u_error = EFAULT;
403 }
404