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