xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 898732d7)
1 /*	uipc_syscalls.c	4.39	82/12/28	*/
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 "../h/descrip.h"
16 #include "../h/uio.h"
17 
18 /*
19  * System call interface to the socket abstraction.
20  */
21 
22 socket()
23 {
24 	register struct a {
25 		int	domain;
26 		int	type;
27 		int	protocol;
28 		struct	socketopt *opt;
29 	} *uap = (struct a *)u.u_ap;
30 	struct socket *so;
31 	register struct file *fp;
32 	struct socketopt aopt;
33 
34 	u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
35 	if (u.u_error)
36 		return;
37 	if ((fp = falloc()) == NULL)
38 		goto freeopt;
39 	fp->f_flag = FREAD|FWRITE;
40 	fp->f_type = DTYPE_SOCKET;
41 	u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol, &aopt);
42 	if (u.u_error)
43 		goto bad;
44 	fp->f_socket = so;
45 freeopt:
46 	if (uap->opt)
47 		(void) m_free(dtom(aopt.so_optdata));
48 	return;
49 bad:
50 	u.u_ofile[u.u_r.r_val1] = 0;
51 	fp->f_count = 0;
52 	goto freeopt;
53 }
54 
55 bind()
56 {
57 	register struct a {
58 		int	s;
59 		caddr_t	name;
60 		int	namelen;
61 		struct	socketopt *opt;
62 	} *uap = (struct a *)u.u_ap;
63 	register struct file *fp;
64 	struct mbuf *nam;
65 	struct socketopt aopt;
66 
67 	fp = getf(uap->s);
68 	if (fp == 0)
69 		return;
70 	if (fp->f_type != DTYPE_SOCKET) {
71 		u.u_error = ENOTSOCK;
72 		return;
73 	}
74 	u.u_error = sockname(&nam, uap->name, uap->namelen);
75 	if (u.u_error)
76 		return;
77 	u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
78 	if (u.u_error) {
79 		m_freem(nam);
80 		goto freeopt;
81 	}
82 	u.u_error = sobind(fp->f_socket, nam, &aopt);
83 	m_freem(nam);
84 freeopt:
85 	if (uap->opt)
86 		(void) m_free(dtom(aopt.so_optdata));
87 }
88 
89 listen()
90 {
91 	register struct a {
92 		int	s;
93 		int	backlog;
94 	} *uap = (struct a *)u.u_ap;
95 	register struct file *fp;
96 
97 	fp = getf(uap->s);
98 	if (fp == 0)
99 		return;
100 	if (fp->f_type != DTYPE_SOCKET) {
101 		u.u_error = ENOTSOCK;
102 		return;
103 	}
104 	u.u_error = solisten(fp->f_socket, uap->backlog);
105 }
106 
107 accept()
108 {
109 	register struct a {
110 		int	s;
111 		caddr_t	name;
112 		int	*anamelen;
113 		struct	socketopt *opt;
114 	} *uap = (struct a *)u.u_ap;
115 	register struct file *fp;
116 	struct mbuf *nam;
117 	struct socketopt aopt;
118 	int namelen;
119 	int s;
120 	register struct socket *so;
121 
122 	if (uap->name == 0)
123 		goto noname;
124 	u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
125 		sizeof (namelen));
126 	if (u.u_error)
127 		return;
128 	if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
129 		u.u_error = EFAULT;
130 		return;
131 	}
132 noname:
133 	u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
134 	if (u.u_error)
135 		return;
136 	fp = getf(uap->s);
137 	if (fp == 0)
138 		goto bad;
139 	if (fp->f_type != DTYPE_SOCKET) {
140 		u.u_error = ENOTSOCK;
141 		goto bad;
142 	}
143 	s = splnet();
144 	so = fp->f_socket;
145 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
146 		u.u_error = EINVAL;
147 		splx(s);
148 		goto bad;
149 	}
150 	if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
151 		u.u_error = EWOULDBLOCK;
152 		splx(s);
153 		goto bad;
154 	}
155 	while (so->so_qlen == 0 && so->so_error == 0) {
156 		if (so->so_state & SS_CANTRCVMORE) {
157 			so->so_error = ECONNABORTED;
158 			break;
159 		}
160 		sleep((caddr_t)&so->so_timeo, PZERO+1);
161 	}
162 	if (so->so_error) {
163 		u.u_error = so->so_error;
164 		splx(s);
165 		goto bad;
166 	}
167 	if ((so->so_options & SO_NEWFDONCONN) == 0) {
168 		struct socket *nso = so->so_q;
169 		(void) soqremque(nso, 1);
170 		u.u_error = soclose(so, 1);
171 		fp->f_socket = nso;
172 		nso->so_q = 0;
173 		so = nso;
174 		goto ret;
175 	}
176 	if (ufalloc() < 0) {
177 		splx(s);
178 		goto bad;
179 	}
180 	fp = falloc();
181 	if (fp == 0) {
182 		u.u_ofile[u.u_r.r_val1] = 0;
183 		splx(s);
184 		goto bad;
185 	}
186 	{ struct socket *aso = so->so_q;
187 	  if (soqremque(aso, 1) == 0)
188 		panic("accept");
189 	  so = aso;
190 	}
191 	fp->f_type = DTYPE_SOCKET;
192 	fp->f_flag = FREAD|FWRITE;
193 	fp->f_socket = so;
194 ret:
195 	nam = m_get(M_WAIT, MT_SONAME);
196 	(void) soaccept(so, nam, &aopt);
197 	if (uap->name) {
198 		if (namelen > nam->m_len)
199 			namelen = nam->m_len;
200 		/* SHOULD COPY OUT A CHAIN HERE */
201 		(void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
202 		    (u_int)namelen);
203 		(void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
204 		    sizeof (*uap->anamelen));
205 	}
206 	m_freem(nam);
207 	splx(s);
208 bad:
209 	if (uap->opt)
210 		(void) m_free(dtom(aopt.so_optdata));
211 }
212 
213 connect()
214 {
215 	register struct a {
216 		int	s;
217 		caddr_t	name;
218 		int	namelen;
219 		struct	socketopt *opt;
220 	} *uap = (struct a *)u.u_ap;
221 	register struct file *fp;
222 	register struct socket *so;
223 	struct mbuf *nam;
224 	struct socketopt aopt;
225 	int s;
226 
227 	fp = getf(uap->s);
228 	if (fp == 0)
229 		return;
230 	if (fp->f_type != DTYPE_SOCKET) {
231 		u.u_error = ENOTSOCK;
232 		return;
233 	}
234 	so = fp->f_socket;
235 	u.u_error = sockname(&nam, uap->name, uap->namelen);
236 	if (u.u_error)
237 		return;
238 	u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
239 	if (u.u_error) {
240 		m_freem(nam);
241 		return;
242 	}
243 	u.u_error = soconnect(so, nam, &aopt);
244 	if (u.u_error)
245 		goto bad;
246 	s = splnet();
247 	if ((so->so_state & SS_NBIO) &&
248 	    (so->so_state & SS_ISCONNECTING)) {
249 		u.u_error = EINPROGRESS;
250 		splx(s);
251 		goto bad;
252 	}
253 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
254 		sleep((caddr_t)&so->so_timeo, PZERO+1);
255 	u.u_error = so->so_error;
256 	so->so_error = 0;
257 	splx(s);
258 bad:
259 	m_freem(nam);
260 	if (uap->opt)
261 		(void) m_free(dtom(aopt.so_optdata));
262 	return;
263 }
264 
265 socketpair()
266 {
267 
268 	u.u_error = ENOENT;
269 }
270 
271 sendto()
272 {
273 	register struct a {
274 		int	s;
275 		caddr_t	buf;
276 		int	len;
277 		int	flags;
278 		caddr_t	to;
279 		int	tolen;
280 	} *uap = (struct a *)u.u_ap;
281 	register struct file *fp;
282 	struct uio auio;
283 	struct iovec aiov;
284 	struct mbuf *to;
285 
286 	fp = getf(uap->s);
287 	if (fp == 0)
288 		return;
289 	if (fp->f_type != DTYPE_SOCKET) {
290 		u.u_error = ENOTSOCK;
291 		return;
292 	}
293 	auio.uio_iov = &aiov;
294 	auio.uio_iovcnt = 1;
295 	aiov.iov_base = uap->buf;
296 	aiov.iov_len = uap->len;
297 	auio.uio_resid = uap->len;
298 	auio.uio_segflg = 0;
299 	auio.uio_offset = 0;	/* XXX */
300 	if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
301 		u.u_error = EFAULT;
302 		return;
303 	}
304 	u.u_error = sockname(&to, uap->to, uap->tolen);
305 	if (u.u_error)
306 		goto bad;
307 	u.u_error = sosend(fp->f_socket, to, &auio, uap->flags);
308 	u.u_r.r_val1 = uap->len - auio.uio_resid;
309 bad:
310 	m_freem(to);
311 }
312 
313 send()
314 {
315 	register struct a {
316 		int	s;
317 		caddr_t	buf;
318 		int	len;
319 		int	flags;
320 	} *uap = (struct a *)u.u_ap;
321 	register struct file *fp;
322 	struct uio auio;
323 	struct iovec aiov;
324 
325 	fp = getf(uap->s);
326 	if (fp == 0)
327 		return;
328 	if (fp->f_type != DTYPE_SOCKET) {
329 		u.u_error = ENOTSOCK;
330 		return;
331 	}
332 	auio.uio_iov = &aiov;
333 	auio.uio_iovcnt = 1;
334 	aiov.iov_base = uap->buf;
335 	aiov.iov_len = uap->len;
336 	auio.uio_resid = uap->len;
337 	auio.uio_segflg = 0;
338 	auio.uio_offset = 0;	/* XXX */
339 	if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
340 		u.u_error = EFAULT;
341 		return;
342 	}
343 	if (u.u_error)
344 		return;
345 	u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags);
346 	u.u_r.r_val1 = uap->len - auio.uio_resid;
347 }
348 
349 recvfrom()
350 {
351 	register struct a {
352 		int	s;
353 		caddr_t	buf;
354 		int	len;
355 		int	flags;
356 		caddr_t	from;
357 		int	*fromlenaddr;
358 	} *uap = (struct a *)u.u_ap;
359 	register struct file *fp;
360 	struct uio auio;
361 	struct iovec aiov;
362 	struct mbuf *from;
363 	int fromlen;
364 
365 	u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen,
366 		sizeof (fromlen));
367 	if (u.u_error)
368 		return;
369 	fp = getf(uap->s);
370 	if (fp == 0)
371 		return;
372 	if (fp->f_type != DTYPE_SOCKET) {
373 		u.u_error = ENOTSOCK;
374 		return;
375 	}
376 	auio.uio_iov = &aiov;
377 	auio.uio_iovcnt = 1;
378 	aiov.iov_base = uap->buf;
379 	aiov.iov_len = uap->len;
380 	auio.uio_resid = uap->len;
381 	auio.uio_segflg = 0;
382 	auio.uio_offset = 0;	/* XXX */
383 	if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0)  {
384 		u.u_error = EFAULT;
385 		return;
386 	}
387 	from = 0;
388 	u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags);
389 	if (u.u_error)
390 		goto bad;
391 	if (from == 0)
392 		fromlen = 0;
393 	else {
394 		if (fromlen > from->m_len)
395 			fromlen = from->m_len;
396 		u.u_error = copyout(mtod(from, caddr_t), uap->from,
397 			(u_int)fromlen);
398 		if (u.u_error)
399 			goto bad;
400 	}
401 	u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr,
402 	    sizeof (fromlen));
403 	if (u.u_error)
404 		goto bad;
405 	u.u_r.r_val1 = uap->len - auio.uio_resid;
406 bad:
407 	if (from)
408 		m_freem(from);
409 	return;
410 }
411 
412 recv()
413 {
414 	register struct a {
415 		int	s;
416 		caddr_t	buf;
417 		int	len;
418 		int	flags;
419 	} *uap = (struct a *)u.u_ap;
420 	register struct file *fp;
421 	struct uio auio;
422 	struct iovec aiov;
423 
424 	fp = getf(uap->s);
425 	if (fp == 0)
426 		return;
427 	if (fp->f_type != DTYPE_SOCKET) {
428 		u.u_error = ENOTSOCK;
429 		return;
430 	}
431 	auio.uio_iov = &aiov;
432 	auio.uio_iovcnt = 1;
433 	aiov.iov_base = uap->buf;
434 	aiov.iov_len = uap->len;
435 	auio.uio_resid = uap->len;
436 	auio.uio_segflg = 0;
437 	auio.uio_offset = 0;	/* XXX */
438 	if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0)  {
439 		u.u_error = EFAULT;
440 		return;
441 	}
442 	u.u_error =
443 	    soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags);
444 	u.u_r.r_val1 = uap->len - auio.uio_resid;
445 }
446 
447 sendmsg()
448 {
449 
450 	u.u_error = EINVAL;
451 }
452 
453 recvmsg()
454 {
455 
456 	u.u_error = EINVAL;
457 }
458 
459 shutdown()
460 {
461 
462 	u.u_error = EINVAL;
463 }
464 
465 pipe()
466 {
467 	register struct file *rf, *wf;
468 	struct socket *rso, *wso;
469 	int r;
470 
471 	u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0,
472 		(struct socketopt *)0);
473 	if (u.u_error)
474 		return;
475 	u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0,
476 		(struct socketopt *)0);
477 	if (u.u_error)
478 		goto free;
479 	rf = falloc();
480 	if (rf == NULL)
481 		goto free2;
482 	r = u.u_r.r_val1;
483 	rf->f_flag = FREAD;
484 	rf->f_type = DTYPE_SOCKET;
485 	rf->f_socket = rso;
486 	wf = falloc();
487 	if (wf == NULL)
488 		goto free3;
489 	wf->f_flag = FWRITE;
490 	wf->f_type = DTYPE_SOCKET;
491 	wf->f_socket = wso;
492 	u.u_r.r_val2 = u.u_r.r_val1;
493 	u.u_r.r_val1 = r;
494 	if (piconnect(wso, rso) == 0)
495 		goto free4;
496 	return;
497 free4:
498 	wf->f_count = 0;
499 	u.u_ofile[u.u_r.r_val2] = 0;
500 free3:
501 	rf->f_count = 0;
502 	u.u_ofile[r] = 0;
503 free2:
504 	wso->so_state |= SS_NOFDREF;
505 	sofree(wso);
506 free:
507 	rso->so_state |= SS_NOFDREF;
508 	sofree(rso);
509 }
510 
511 /*
512  * Get socket address.
513  */
514 ssocketaddr()
515 {
516 	register struct a {
517 		int	fdes;
518 		struct	sockaddr *asa;
519 	} *uap = (struct a *)u.u_ap;
520 	register struct file *fp;
521 	register struct socket *so;
522 	struct mbuf *m;
523 
524 	fp = getf(uap->fdes);
525 	if (fp == 0)
526 		return;
527 	if (fp->f_type != DTYPE_SOCKET) {
528 		u.u_error = ENOTSOCK;
529 		return;
530 	}
531 	so = fp->f_socket;
532 	m = m_getclr(M_WAIT, MT_SONAME);
533 	u.u_error =
534 		(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
535 	if (u.u_error)
536 		goto bad;
537 	u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa,
538 		sizeof (struct sockaddr));
539 bad:
540 	m_freem(m);
541 }
542 
543 sockname(aname, name, namelen)
544 	struct mbuf **aname;
545 	caddr_t name;
546 	int namelen;
547 {
548 	register struct mbuf *m;
549 	int error;
550 
551 	if (namelen > MLEN)
552 		return (EINVAL);
553 	m = m_get(M_WAIT, MT_SONAME);
554 	m->m_len = namelen;
555 	error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
556 	if (error)
557 		(void) m_free(m);
558 	else
559 		*aname = m;
560 	return (error);
561 }
562 
563 sockopt(so, opt)
564 	register struct socketopt *so;
565 	caddr_t opt;
566 {
567 	register struct mbuf *m;
568 	int error;
569 
570 	if (opt == 0) {
571 		so->so_optlen = 0;
572 		so->so_optdata = 0;
573 		return (0);
574 	}
575 	error = copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt));
576 	if (error)
577 		return (error);
578 	if (so->so_optlen < 0 || so->so_optlen > MLEN)
579 		return (EINVAL);
580 	m = m_get(M_WAIT, MT_SOOPTS);
581 	m->m_len = so->so_optlen;
582 	error = copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len);
583 	if (error) {
584 		(void) m_free(m);
585 		return (error);
586 	}
587 	so->so_optdata = mtod(m, caddr_t);
588 	return (0);
589 }
590