xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 3f839ad3)
1 /*	uipc_syscalls.c	4.37	82/11/15	*/
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 	if (copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, sizeof (namelen))) {
125 		u.u_error = EFAULT;
126 		return;
127 	}
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);
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 	if (copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, sizeof (fromlen))) {
366 		u.u_error = EFAULT;
367 		return;
368 	}
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 		if (copyout(mtod(from, caddr_t), uap->from, (u_int)fromlen)) {
397 			u.u_error = EFAULT;
398 			goto bad;
399 		}
400 	}
401 	if (copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr,
402 	    sizeof (fromlen))) {
403 		u.u_error = EFAULT;
404 		goto bad;
405 	}
406 	u.u_r.r_val1 = uap->len - auio.uio_resid;
407 bad:
408 	if (from)
409 		m_freem(from);
410 	return;
411 }
412 
413 recv()
414 {
415 	register struct a {
416 		int	s;
417 		caddr_t	buf;
418 		int	len;
419 		int	flags;
420 	} *uap = (struct a *)u.u_ap;
421 	register struct file *fp;
422 	struct uio auio;
423 	struct iovec aiov;
424 
425 	fp = getf(uap->s);
426 	if (fp == 0)
427 		return;
428 	if (fp->f_type != DTYPE_SOCKET) {
429 		u.u_error = ENOTSOCK;
430 		return;
431 	}
432 	auio.uio_iov = &aiov;
433 	auio.uio_iovcnt = 1;
434 	aiov.iov_base = uap->buf;
435 	aiov.iov_len = uap->len;
436 	auio.uio_resid = uap->len;
437 	auio.uio_segflg = 0;
438 	auio.uio_offset = 0;	/* XXX */
439 	if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0)  {
440 		u.u_error = EFAULT;
441 		return;
442 	}
443 	u.u_error =
444 	    soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags);
445 	u.u_r.r_val1 = uap->len - auio.uio_resid;
446 }
447 
448 sendmsg()
449 {
450 
451 	u.u_error = EINVAL;
452 }
453 
454 recvmsg()
455 {
456 
457 	u.u_error = EINVAL;
458 }
459 
460 shutdown()
461 {
462 
463 	u.u_error = EINVAL;
464 }
465 
466 pipe()
467 {
468 	register struct file *rf, *wf;
469 	struct socket *rso, *wso;
470 	int r;
471 
472 	u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0,
473 		(struct socketopt *)0);
474 	if (u.u_error)
475 		return;
476 	u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0,
477 		(struct socketopt *)0);
478 	if (u.u_error)
479 		goto free;
480 	rf = falloc();
481 	if (rf == NULL)
482 		goto free2;
483 	r = u.u_r.r_val1;
484 	rf->f_flag = FREAD;
485 	rf->f_type = DTYPE_SOCKET;
486 	rf->f_socket = rso;
487 	wf = falloc();
488 	if (wf == NULL)
489 		goto free3;
490 	wf->f_flag = FWRITE;
491 	wf->f_type = DTYPE_SOCKET;
492 	wf->f_socket = wso;
493 	u.u_r.r_val2 = u.u_r.r_val1;
494 	u.u_r.r_val1 = r;
495 	if (piconnect(wso, rso) == 0)
496 		goto free4;
497 	return;
498 free4:
499 	wf->f_count = 0;
500 	u.u_ofile[u.u_r.r_val2] = 0;
501 free3:
502 	rf->f_count = 0;
503 	u.u_ofile[r] = 0;
504 free2:
505 	wso->so_state |= SS_NOFDREF;
506 	sofree(wso);
507 free:
508 	rso->so_state |= SS_NOFDREF;
509 	sofree(rso);
510 }
511 
512 /*
513  * Get socket address.
514  */
515 ssocketaddr()
516 {
517 	register struct a {
518 		int	fdes;
519 		struct	sockaddr *asa;
520 	} *uap = (struct a *)u.u_ap;
521 	register struct file *fp;
522 	register struct socket *so;
523 	struct mbuf *m;
524 
525 	fp = getf(uap->fdes);
526 	if (fp == 0)
527 		return;
528 	if (fp->f_type != DTYPE_SOCKET) {
529 		u.u_error = ENOTSOCK;
530 		return;
531 	}
532 	so = fp->f_socket;
533 	m = m_getclr(M_WAIT);
534 	u.u_error =
535 		(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
536 	if (u.u_error)
537 		goto bad;
538 	if (copyout(mtod(m, caddr_t), (caddr_t)uap->asa, sizeof (struct sockaddr)))
539 		u.u_error = EFAULT;
540 bad:
541 	m_freem(m);
542 }
543 
544 sockname(aname, name, namelen)
545 	struct mbuf **aname;
546 	caddr_t name;
547 	int namelen;
548 {
549 	register struct mbuf *m;
550 
551 	if (namelen > MLEN)
552 		return (EINVAL);
553 	m = m_get(M_WAIT);
554 	m->m_len = namelen;
555 	if (copyin(name, mtod(m, caddr_t), (u_int)namelen)) {
556 		(void) m_free(m);
557 		return (EFAULT);
558 	}
559 	*aname = m;
560 	return (0);
561 }
562 
563 sockopt(so, opt)
564 	register struct socketopt *so;
565 	caddr_t opt;
566 {
567 	register struct mbuf *m;
568 
569 	if (opt == 0) {
570 		so->so_optlen = 0;
571 		so->so_optdata = 0;
572 		return (0);
573 	}
574 	if (copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt)))
575 		return (EFAULT);
576 	if (so->so_optlen < 0 || so->so_optlen > MLEN)
577 		return (EINVAL);
578 	m = m_get(M_WAIT);
579 	m->m_len = so->so_optlen;
580 	if (copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len)) {
581 		(void) m_free(m);
582 		return (EFAULT);
583 	}
584 	so->so_optdata = mtod(m, caddr_t);
585 	return (0);
586 }
587