sun
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
127f7d76 1/* uipc_syscalls.c 4.39 82/12/28 */
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
BJ
27 int protocol;
28 struct socketopt *opt;
cc15ab5d 29 } *uap = (struct a *)u.u_ap;
2b4b57cd 30 struct socket *so;
cc15ab5d 31 register struct file *fp;
cf012934 32 struct socketopt aopt;
c8c7dd0e 33
b32450f4 34 u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
dfb67abe 35 if (u.u_error)
cc15ab5d 36 return;
dfb67abe
BJ
37 if ((fp = falloc()) == NULL)
38 goto freeopt;
4147b3f6
BJ
39 fp->f_flag = FREAD|FWRITE;
40 fp->f_type = DTYPE_SOCKET;
76d78581 41 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol, &aopt);
cc15ab5d
BJ
42 if (u.u_error)
43 goto bad;
2b4b57cd 44 fp->f_socket = so;
cf012934
BJ
45freeopt:
46 if (uap->opt)
39d536e6 47 (void) m_free(dtom(aopt.so_optdata));
cc15ab5d
BJ
48 return;
49bad:
50 u.u_ofile[u.u_r.r_val1] = 0;
51 fp->f_count = 0;
cf012934 52 goto freeopt;
c8c7dd0e 53}
ae921915 54
cf012934 55bind()
ae921915 56{
2b4b57cd 57 register struct a {
cf012934
BJ
58 int s;
59 caddr_t name;
60 int namelen;
61 struct socketopt *opt;
2b4b57cd 62 } *uap = (struct a *)u.u_ap;
2b4b57cd 63 register struct file *fp;
cf012934
BJ
64 struct mbuf *nam;
65 struct socketopt aopt;
ae921915 66
cf012934
BJ
67 fp = getf(uap->s);
68 if (fp == 0)
69 return;
70 if (fp->f_type != DTYPE_SOCKET) {
71 u.u_error = ENOTSOCK;
2b4b57cd
BJ
72 return;
73 }
cf012934
BJ
74 u.u_error = sockname(&nam, uap->name, uap->namelen);
75 if (u.u_error)
76 return;
b32450f4 77 u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
cf012934
BJ
78 if (u.u_error) {
79 m_freem(nam);
970108c7 80 goto freeopt;
cf012934
BJ
81 }
82 u.u_error = sobind(fp->f_socket, nam, &aopt);
83 m_freem(nam);
970108c7 84freeopt:
cf012934 85 if (uap->opt)
39d536e6 86 (void) m_free(dtom(aopt.so_optdata));
cf012934
BJ
87}
88
89listen()
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);
2b4b57cd
BJ
98 if (fp == 0)
99 return;
4147b3f6 100 if (fp->f_type != DTYPE_SOCKET) {
2b4b57cd
BJ
101 u.u_error = ENOTSOCK;
102 return;
103 }
cf012934
BJ
104 u.u_error = solisten(fp->f_socket, uap->backlog);
105}
106
107accept()
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;
127f7d76
SL
124 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
125 sizeof (namelen));
126 if (u.u_error)
cf012934 127 return;
b32450f4 128 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
cf012934
BJ
129 u.u_error = EFAULT;
130 return;
131 }
132noname:
b32450f4 133 u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
cf012934
BJ
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 }
2b4b57cd
BJ
143 s = splnet();
144 so = fp->f_socket;
4147b3f6
BJ
145 if ((so->so_options & SO_ACCEPTCONN) == 0) {
146 u.u_error = EINVAL;
147 splx(s);
cf012934 148 goto bad;
4147b3f6
BJ
149 }
150 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd
BJ
151 u.u_error = EWOULDBLOCK;
152 splx(s);
cf012934 153 goto bad;
2b4b57cd 154 }
4147b3f6 155 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
156 if (so->so_state & SS_CANTRCVMORE) {
157 so->so_error = ECONNABORTED;
158 break;
159 }
d08c5322 160 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 161 }
f269ef23
BJ
162 if (so->so_error) {
163 u.u_error = so->so_error;
164 splx(s);
cf012934 165 goto bad;
f269ef23 166 }
4147b3f6
BJ
167 if ((so->so_options & SO_NEWFDONCONN) == 0) {
168 struct socket *nso = so->so_q;
169 (void) soqremque(nso, 1);
6e7edb25 170 u.u_error = soclose(so, 1);
4147b3f6
BJ
171 fp->f_socket = nso;
172 nso->so_q = 0;
173 so = nso;
174 goto ret;
175 }
176 if (ufalloc() < 0) {
177 splx(s);
cf012934 178 goto bad;
4147b3f6
BJ
179 }
180 fp = falloc();
181 if (fp == 0) {
182 u.u_ofile[u.u_r.r_val1] = 0;
2b4b57cd 183 splx(s);
cf012934
BJ
184 goto bad;
185 }
186 { struct socket *aso = so->so_q;
187 if (soqremque(aso, 1) == 0)
188 panic("accept");
189 so = aso;
2b4b57cd 190 }
4147b3f6
BJ
191 fp->f_type = DTYPE_SOCKET;
192 fp->f_flag = FREAD|FWRITE;
cf012934 193 fp->f_socket = so;
4147b3f6 194ret:
cce93e4b 195 nam = m_get(M_WAIT, MT_SONAME);
5a1f132a 196 (void) soaccept(so, nam, &aopt);
cf012934
BJ
197 if (uap->name) {
198 if (namelen > nam->m_len)
199 namelen = nam->m_len;
200 /* SHOULD COPY OUT A CHAIN HERE */
b32450f4
BJ
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,
cf012934
BJ
204 sizeof (*uap->anamelen));
205 }
206 m_freem(nam);
2b4b57cd 207 splx(s);
cf012934
BJ
208bad:
209 if (uap->opt)
39d536e6 210 (void) m_free(dtom(aopt.so_optdata));
ae921915
BJ
211}
212
cf012934 213connect()
c8c7dd0e
BJ
214{
215 register struct a {
cf012934
BJ
216 int s;
217 caddr_t name;
218 int namelen;
219 struct socketopt *opt;
c8c7dd0e 220 } *uap = (struct a *)u.u_ap;
c8c7dd0e
BJ
221 register struct file *fp;
222 register struct socket *so;
cf012934
BJ
223 struct mbuf *nam;
224 struct socketopt aopt;
c8c7dd0e
BJ
225 int s;
226
cf012934 227 fp = getf(uap->s);
c8c7dd0e
BJ
228 if (fp == 0)
229 return;
4147b3f6 230 if (fp->f_type != DTYPE_SOCKET) {
c8c7dd0e
BJ
231 u.u_error = ENOTSOCK;
232 return;
233 }
234 so = fp->f_socket;
cf012934 235 u.u_error = sockname(&nam, uap->name, uap->namelen);
c8c7dd0e
BJ
236 if (u.u_error)
237 return;
b32450f4 238 u.u_error = sockopt(&aopt, (caddr_t)uap->opt);
cf012934
BJ
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;
c8c7dd0e 246 s = splnet();
62364f0e 247 if ((so->so_state & SS_NBIO) &&
cc15ab5d 248 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 249 u.u_error = EINPROGRESS;
cc15ab5d 250 splx(s);
cf012934 251 goto bad;
c8c7dd0e 252 }
cc15ab5d 253 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
254 sleep((caddr_t)&so->so_timeo, PZERO+1);
255 u.u_error = so->so_error;
cc15ab5d
BJ
256 so->so_error = 0;
257 splx(s);
cf012934
BJ
258bad:
259 m_freem(nam);
260 if (uap->opt)
39d536e6 261 (void) m_free(dtom(aopt.so_optdata));
cf012934 262 return;
c8c7dd0e
BJ
263}
264
cf012934
BJ
265socketpair()
266{
267
268 u.u_error = ENOENT;
269}
270
271sendto()
c8c7dd0e
BJ
272{
273 register struct a {
cf012934
BJ
274 int s;
275 caddr_t buf;
276 int len;
277 int flags;
278 caddr_t to;
279 int tolen;
c8c7dd0e
BJ
280 } *uap = (struct a *)u.u_ap;
281 register struct file *fp;
d3d550b5
BJ
282 struct uio auio;
283 struct iovec aiov;
cf012934 284 struct mbuf *to;
c8c7dd0e 285
cf012934 286 fp = getf(uap->s);
c8c7dd0e
BJ
287 if (fp == 0)
288 return;
4147b3f6 289 if (fp->f_type != DTYPE_SOCKET) {
c8c7dd0e
BJ
290 u.u_error = ENOTSOCK;
291 return;
292 }
d3d550b5
BJ
293 auio.uio_iov = &aiov;
294 auio.uio_iovcnt = 1;
cf012934
BJ
295 aiov.iov_base = uap->buf;
296 aiov.iov_len = uap->len;
297 auio.uio_resid = uap->len;
d3d550b5
BJ
298 auio.uio_segflg = 0;
299 auio.uio_offset = 0; /* XXX */
b32450f4 300 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
c8c7dd0e
BJ
301 u.u_error = EFAULT;
302 return;
303 }
cf012934
BJ
304 u.u_error = sockname(&to, uap->to, uap->tolen);
305 if (u.u_error)
306 goto bad;
970108c7 307 u.u_error = sosend(fp->f_socket, to, &auio, uap->flags);
76d78581 308 u.u_r.r_val1 = uap->len - auio.uio_resid;
cf012934
BJ
309bad:
310 m_freem(to);
c8c7dd0e
BJ
311}
312
cf012934 313send()
cc15ab5d
BJ
314{
315 register struct a {
cf012934
BJ
316 int s;
317 caddr_t buf;
318 int len;
319 int flags;
cc15ab5d
BJ
320 } *uap = (struct a *)u.u_ap;
321 register struct file *fp;
a6b6f679
BJ
322 struct uio auio;
323 struct iovec aiov;
cc15ab5d 324
cf012934
BJ
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 */
b32450f4 339 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
cf012934
BJ
340 u.u_error = EFAULT;
341 return;
342 }
343 if (u.u_error)
344 return;
970108c7 345 u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags);
76d78581 346 u.u_r.r_val1 = uap->len - auio.uio_resid;
cf012934
BJ
347}
348
349recvfrom()
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
127f7d76
SL
365 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen,
366 sizeof (fromlen));
367 if (u.u_error)
cf012934 368 return;
cf012934
BJ
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 */
b32450f4 383 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) {
cf012934
BJ
384 u.u_error = EFAULT;
385 return;
386 }
387 from = 0;
970108c7 388 u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags);
cf012934
BJ
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;
127f7d76
SL
396 u.u_error = copyout(mtod(from, caddr_t), uap->from,
397 (u_int)fromlen);
398 if (u.u_error)
cf012934 399 goto bad;
cf012934 400 }
127f7d76
SL
401 u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr,
402 sizeof (fromlen));
403 if (u.u_error)
cf012934 404 goto bad;
cf012934
BJ
405 u.u_r.r_val1 = uap->len - auio.uio_resid;
406bad:
407 if (from)
408 m_freem(from);
409 return;
410}
411
412recv()
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);
cc15ab5d
BJ
425 if (fp == 0)
426 return;
4147b3f6 427 if (fp->f_type != DTYPE_SOCKET) {
cc15ab5d
BJ
428 u.u_error = ENOTSOCK;
429 return;
430 }
a6b6f679
BJ
431 auio.uio_iov = &aiov;
432 auio.uio_iovcnt = 1;
cf012934
BJ
433 aiov.iov_base = uap->buf;
434 aiov.iov_len = uap->len;
435 auio.uio_resid = uap->len;
a6b6f679
BJ
436 auio.uio_segflg = 0;
437 auio.uio_offset = 0; /* XXX */
b32450f4 438 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) {
cc15ab5d
BJ
439 u.u_error = EFAULT;
440 return;
441 }
b32450f4
BJ
442 u.u_error =
443 soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags);
cf012934
BJ
444 u.u_r.r_val1 = uap->len - auio.uio_resid;
445}
446
447sendmsg()
448{
449
450 u.u_error = EINVAL;
451}
452
453recvmsg()
454{
455
456 u.u_error = EINVAL;
457}
458
459shutdown()
460{
461
462 u.u_error = EINVAL;
463}
464
465pipe()
466{
467 register struct file *rf, *wf;
468 struct socket *rso, *wso;
469 int r;
470
4f083fd7
SL
471 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0,
472 (struct socketopt *)0);
2b4b57cd
BJ
473 if (u.u_error)
474 return;
4f083fd7
SL
475 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0,
476 (struct socketopt *)0);
cf012934
BJ
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;
497free4:
498 wf->f_count = 0;
499 u.u_ofile[u.u_r.r_val2] = 0;
500free3:
501 rf->f_count = 0;
502 u.u_ofile[r] = 0;
503free2:
504 wso->so_state |= SS_NOFDREF;
505 sofree(wso);
506free:
507 rso->so_state |= SS_NOFDREF;
508 sofree(rso);
cc15ab5d 509}
a3076b07
BJ
510
511/*
512 * Get socket address.
513 */
514ssocketaddr()
515{
516 register struct a {
517 int fdes;
518 struct sockaddr *asa;
519 } *uap = (struct a *)u.u_ap;
520 register struct file *fp;
05d69517 521 register struct socket *so;
cf012934 522 struct mbuf *m;
a3076b07
BJ
523
524 fp = getf(uap->fdes);
525 if (fp == 0)
526 return;
4147b3f6 527 if (fp->f_type != DTYPE_SOCKET) {
a3076b07
BJ
528 u.u_error = ENOTSOCK;
529 return;
530 }
05d69517 531 so = fp->f_socket;
cce93e4b 532 m = m_getclr(M_WAIT, MT_SONAME);
05d69517 533 u.u_error =
cf012934 534 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
05d69517 535 if (u.u_error)
cf012934 536 goto bad;
127f7d76
SL
537 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa,
538 sizeof (struct sockaddr));
cf012934
BJ
539bad:
540 m_freem(m);
541}
542
543sockname(aname, name, namelen)
544 struct mbuf **aname;
545 caddr_t name;
546 int namelen;
547{
548 register struct mbuf *m;
127f7d76 549 int error;
cf012934
BJ
550
551 if (namelen > MLEN)
552 return (EINVAL);
cce93e4b 553 m = m_get(M_WAIT, MT_SONAME);
cf012934 554 m->m_len = namelen;
127f7d76
SL
555 error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
556 if (error)
cf012934 557 (void) m_free(m);
127f7d76
SL
558 else
559 *aname = m;
560 return (error);
cf012934
BJ
561}
562
563sockopt(so, opt)
564 register struct socketopt *so;
565 caddr_t opt;
566{
567 register struct mbuf *m;
127f7d76 568 int error;
cf012934
BJ
569
570 if (opt == 0) {
571 so->so_optlen = 0;
572 so->so_optdata = 0;
573 return (0);
574 }
127f7d76
SL
575 error = copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt));
576 if (error)
577 return (error);
cf012934
BJ
578 if (so->so_optlen < 0 || so->so_optlen > MLEN)
579 return (EINVAL);
cce93e4b 580 m = m_get(M_WAIT, MT_SOOPTS);
cf012934 581 m->m_len = so->so_optlen;
127f7d76
SL
582 error = copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len);
583 if (error) {
cf012934 584 (void) m_free(m);
127f7d76 585 return (error);
cf012934
BJ
586 }
587 so->so_optdata = mtod(m, caddr_t);
588 return (0);
2752c877 589}