add memory filesystem initialization
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
da7c5cc6 1/*
da7c5cc6 2 *
96e6449f 3 * Redistribution and use in source and binary forms are permitted
616d42db
KB
4 * provided that the above copyright notice and this paragraph are
5 * duplicated in all such forms and that any documentation,
6 * advertising materials, and other materials related to such
7 * distribution and use acknowledge that the software was developed
8 * by the University of California, Berkeley. The name of the
9 * University may not be used to endorse or promote products derived
10 * from this software without specific prior written permission.
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
12 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
13 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96e6449f 14 *
c4ec2128 15 * @(#)uipc_syscalls.c 7.10 (Berkeley) %G%
da7c5cc6 16 */
c8c7dd0e 17
94368568 18#include "param.h"
94368568 19#include "user.h"
6d47a3da 20#include "proc.h"
94368568 21#include "file.h"
94368568 22#include "buf.h"
6d47a3da 23#include "malloc.h"
94368568
JB
24#include "mbuf.h"
25#include "protosw.h"
26#include "socket.h"
27#include "socketvar.h"
4147b3f6 28
c8c7dd0e 29/*
cf012934 30 * System call interface to the socket abstraction.
c8c7dd0e
BJ
31 */
32
88a7a62a
SL
33struct file *getsock();
34extern struct fileops socketops;
35
cf012934 36socket()
c8c7dd0e 37{
cc15ab5d 38 register struct a {
cf012934 39 int domain;
cc15ab5d 40 int type;
cf012934 41 int protocol;
cc15ab5d 42 } *uap = (struct a *)u.u_ap;
2b4b57cd 43 struct socket *so;
0c9a45f0
KM
44 struct file *fp;
45 int fd;
c8c7dd0e 46
0c9a45f0 47 if (u.u_error = falloc(&fp, &fd))
66f52238 48 return;
4147b3f6
BJ
49 fp->f_flag = FREAD|FWRITE;
50 fp->f_type = DTYPE_SOCKET;
88a7a62a 51 fp->f_ops = &socketops;
66f52238 52 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol);
cc15ab5d
BJ
53 if (u.u_error)
54 goto bad;
88a7a62a 55 fp->f_data = (caddr_t)so;
0c9a45f0 56 u.u_r.r_val1 = fd;
cc15ab5d
BJ
57 return;
58bad:
0c9a45f0
KM
59 u.u_ofile[fd] = 0;
60 crfree(fp->f_cred);
cc15ab5d 61 fp->f_count = 0;
c8c7dd0e 62}
ae921915 63
cf012934 64bind()
ae921915 65{
2b4b57cd 66 register struct a {
cf012934
BJ
67 int s;
68 caddr_t name;
69 int namelen;
2b4b57cd 70 } *uap = (struct a *)u.u_ap;
2b4b57cd 71 register struct file *fp;
cf012934 72 struct mbuf *nam;
ae921915 73
88a7a62a 74 fp = getsock(uap->s);
cf012934
BJ
75 if (fp == 0)
76 return;
98447d3f 77 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
cf012934
BJ
78 if (u.u_error)
79 return;
88a7a62a 80 u.u_error = sobind((struct socket *)fp->f_data, nam);
cf012934 81 m_freem(nam);
cf012934
BJ
82}
83
84listen()
85{
86 register struct a {
87 int s;
88 int backlog;
89 } *uap = (struct a *)u.u_ap;
90 register struct file *fp;
91
88a7a62a 92 fp = getsock(uap->s);
2b4b57cd
BJ
93 if (fp == 0)
94 return;
88a7a62a 95 u.u_error = solisten((struct socket *)fp->f_data, uap->backlog);
cf012934
BJ
96}
97
f4d2893a
MK
98#ifdef COMPAT_43
99accept()
100{
101 accept1(0);
102}
103
104oaccept()
105{
106 accept1(1);
107}
108
109accept1(compat_43)
110#else
cf012934 111accept()
f4d2893a 112#endif
cf012934
BJ
113{
114 register struct a {
115 int s;
116 caddr_t name;
117 int *anamelen;
cf012934 118 } *uap = (struct a *)u.u_ap;
0c9a45f0 119 struct file *fp;
cf012934 120 struct mbuf *nam;
cf012934
BJ
121 int namelen;
122 int s;
123 register struct socket *so;
124
125 if (uap->name == 0)
126 goto noname;
127f7d76
SL
127 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
128 sizeof (namelen));
129 if (u.u_error)
cf012934 130 return;
b32450f4 131 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
cf012934
BJ
132 u.u_error = EFAULT;
133 return;
134 }
135noname:
88a7a62a 136 fp = getsock(uap->s);
cf012934 137 if (fp == 0)
66f52238 138 return;
2b4b57cd 139 s = splnet();
88a7a62a 140 so = (struct socket *)fp->f_data;
4147b3f6
BJ
141 if ((so->so_options & SO_ACCEPTCONN) == 0) {
142 u.u_error = EINVAL;
143 splx(s);
66f52238 144 return;
4147b3f6
BJ
145 }
146 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd
BJ
147 u.u_error = EWOULDBLOCK;
148 splx(s);
66f52238 149 return;
2b4b57cd 150 }
4147b3f6 151 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
152 if (so->so_state & SS_CANTRCVMORE) {
153 so->so_error = ECONNABORTED;
154 break;
155 }
d08c5322 156 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 157 }
f269ef23
BJ
158 if (so->so_error) {
159 u.u_error = so->so_error;
f4ed5810 160 so->so_error = 0;
f269ef23 161 splx(s);
66f52238 162 return;
f269ef23 163 }
0c9a45f0 164 if (u.u_error = falloc(&fp, &u.u_r.r_val1)) {
2b4b57cd 165 splx(s);
66f52238 166 return;
cf012934
BJ
167 }
168 { struct socket *aso = so->so_q;
169 if (soqremque(aso, 1) == 0)
170 panic("accept");
171 so = aso;
2b4b57cd 172 }
4147b3f6
BJ
173 fp->f_type = DTYPE_SOCKET;
174 fp->f_flag = FREAD|FWRITE;
88a7a62a
SL
175 fp->f_ops = &socketops;
176 fp->f_data = (caddr_t)so;
cce93e4b 177 nam = m_get(M_WAIT, MT_SONAME);
66f52238 178 (void) soaccept(so, nam);
cf012934 179 if (uap->name) {
f4d2893a
MK
180#ifdef COMPAT_43
181 if (compat_43)
182 mtod(nam, struct osockaddr *)->sa_family =
183 mtod(nam, struct sockaddr *)->sa_family;
184#endif
cf012934
BJ
185 if (namelen > nam->m_len)
186 namelen = nam->m_len;
187 /* SHOULD COPY OUT A CHAIN HERE */
b32450f4
BJ
188 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
189 (u_int)namelen);
190 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
cf012934
BJ
191 sizeof (*uap->anamelen));
192 }
193 m_freem(nam);
2b4b57cd 194 splx(s);
ae921915
BJ
195}
196
cf012934 197connect()
c8c7dd0e
BJ
198{
199 register struct a {
cf012934
BJ
200 int s;
201 caddr_t name;
202 int namelen;
c8c7dd0e 203 } *uap = (struct a *)u.u_ap;
c8c7dd0e
BJ
204 register struct file *fp;
205 register struct socket *so;
cf012934 206 struct mbuf *nam;
c8c7dd0e
BJ
207 int s;
208
88a7a62a 209 fp = getsock(uap->s);
c8c7dd0e
BJ
210 if (fp == 0)
211 return;
88a7a62a 212 so = (struct socket *)fp->f_data;
a7a77c02
MK
213 if ((so->so_state & SS_NBIO) &&
214 (so->so_state & SS_ISCONNECTING)) {
6222acc3 215 u.u_error = EALREADY;
a7a77c02
MK
216 return;
217 }
98447d3f 218 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
c8c7dd0e
BJ
219 if (u.u_error)
220 return;
66f52238 221 u.u_error = soconnect(so, nam);
cf012934
BJ
222 if (u.u_error)
223 goto bad;
6222acc3
MK
224 if ((so->so_state & SS_NBIO) &&
225 (so->so_state & SS_ISCONNECTING)) {
226 u.u_error = EINPROGRESS;
227 m_freem(nam);
228 return;
229 }
c8c7dd0e 230 s = splnet();
88a7a62a
SL
231 if (setjmp(&u.u_qsave)) {
232 if (u.u_error == 0)
233 u.u_error = EINTR;
234 goto bad2;
c8c7dd0e 235 }
cc15ab5d 236 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
237 sleep((caddr_t)&so->so_timeo, PZERO+1);
238 u.u_error = so->so_error;
cc15ab5d 239 so->so_error = 0;
88a7a62a 240bad2:
cc15ab5d 241 splx(s);
cf012934 242bad:
6750daae 243 so->so_state &= ~SS_ISCONNECTING;
cf012934 244 m_freem(nam);
c8c7dd0e
BJ
245}
246
cf012934
BJ
247socketpair()
248{
5a48956d
SL
249 register struct a {
250 int domain;
251 int type;
252 int protocol;
253 int *rsv;
254 } *uap = (struct a *)u.u_ap;
0c9a45f0 255 struct file *fp1, *fp2;
5a48956d 256 struct socket *so1, *so2;
0c9a45f0 257 int fd, sv[2];
cf012934 258
5a48956d
SL
259 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
260 u.u_error = EFAULT;
261 return;
262 }
263 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
264 if (u.u_error)
265 return;
266 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
267 if (u.u_error)
b242cf10 268 goto free1;
0c9a45f0 269 if (u.u_error = falloc(&fp1, &fd))
5a48956d 270 goto free2;
0c9a45f0 271 sv[0] = fd;
5a48956d
SL
272 fp1->f_flag = FREAD|FWRITE;
273 fp1->f_type = DTYPE_SOCKET;
274 fp1->f_ops = &socketops;
275 fp1->f_data = (caddr_t)so1;
0c9a45f0 276 if (u.u_error = falloc(&fp2, &fd))
5a48956d
SL
277 goto free3;
278 fp2->f_flag = FREAD|FWRITE;
279 fp2->f_type = DTYPE_SOCKET;
280 fp2->f_ops = &socketops;
281 fp2->f_data = (caddr_t)so2;
0c9a45f0 282 sv[1] = fd;
5a48956d
SL
283 u.u_error = soconnect2(so1, so2);
284 if (u.u_error)
285 goto free4;
33446404
MK
286 if (uap->type == SOCK_DGRAM) {
287 /*
288 * Datagram socket connection is asymmetric.
289 */
290 u.u_error = soconnect2(so2, so1);
291 if (u.u_error)
292 goto free4;
293 }
5a48956d 294 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
0c9a45f0
KM
295 u.u_r.r_val1 = sv[0];
296 u.u_r.r_val2 = sv[1];
5a48956d
SL
297 return;
298free4:
0c9a45f0 299 crfree(fp2->f_cred);
5a48956d
SL
300 fp2->f_count = 0;
301 u.u_ofile[sv[1]] = 0;
302free3:
0c9a45f0 303 crfree(fp1->f_cred);
5a48956d
SL
304 fp1->f_count = 0;
305 u.u_ofile[sv[0]] = 0;
306free2:
8011f5df 307 (void)soclose(so2);
b242cf10 308free1:
8011f5df 309 (void)soclose(so1);
cf012934
BJ
310}
311
312sendto()
c8c7dd0e
BJ
313{
314 register struct a {
cf012934
BJ
315 int s;
316 caddr_t buf;
317 int len;
318 int flags;
319 caddr_t to;
320 int tolen;
c8c7dd0e 321 } *uap = (struct a *)u.u_ap;
88a7a62a 322 struct msghdr msg;
d3d550b5 323 struct iovec aiov;
c8c7dd0e 324
88a7a62a
SL
325 msg.msg_name = uap->to;
326 msg.msg_namelen = uap->tolen;
327 msg.msg_iov = &aiov;
328 msg.msg_iovlen = 1;
cf012934
BJ
329 aiov.iov_base = uap->buf;
330 aiov.iov_len = uap->len;
88a7a62a 331 msg.msg_accrights = 0;
6d47a3da 332 msg.msg_control = 0;
88a7a62a 333 sendit(uap->s, &msg, uap->flags);
c8c7dd0e
BJ
334}
335
6d47a3da 336#ifdef COMPAT_43
f4d2893a 337
6d47a3da 338osend()
cc15ab5d
BJ
339{
340 register struct a {
cf012934
BJ
341 int s;
342 caddr_t buf;
343 int len;
344 int flags;
cc15ab5d 345 } *uap = (struct a *)u.u_ap;
88a7a62a 346 struct msghdr msg;
a6b6f679 347 struct iovec aiov;
cc15ab5d 348
88a7a62a
SL
349 msg.msg_name = 0;
350 msg.msg_namelen = 0;
351 msg.msg_iov = &aiov;
352 msg.msg_iovlen = 1;
cf012934
BJ
353 aiov.iov_base = uap->buf;
354 aiov.iov_len = uap->len;
88a7a62a 355 msg.msg_accrights = 0;
6d47a3da 356 msg.msg_control = 0;
88a7a62a
SL
357 sendit(uap->s, &msg, uap->flags);
358}
359
6d47a3da
MK
360osendmsg()
361{
362 register struct a {
363 int s;
364 caddr_t msg;
365 int flags;
366 } *uap = (struct a *)u.u_ap;
367 struct msghdr msg;
368 struct iovec aiov[MSG_MAXIOVLEN];
369
370 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
371 if (u.u_error)
372 return;
373 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
374 u.u_error = EMSGSIZE;
375 return;
376 }
377 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
378 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
379 if (u.u_error)
380 return;
381 msg.msg_control = 0;
382 msg.msg_controllen = 0;
383 sendit(uap->s, &msg, uap->flags);
384}
385#endif
386
88a7a62a
SL
387sendmsg()
388{
389 register struct a {
390 int s;
391 caddr_t msg;
392 int flags;
393 } *uap = (struct a *)u.u_ap;
394 struct msghdr msg;
395 struct iovec aiov[MSG_MAXIOVLEN];
396
397 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
398 if (u.u_error)
399 return;
400 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
401 u.u_error = EMSGSIZE;
cf012934
BJ
402 return;
403 }
6d47a3da 404 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a 405 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
cf012934
BJ
406 if (u.u_error)
407 return;
88a7a62a 408 msg.msg_iov = aiov;
88a7a62a
SL
409 sendit(uap->s, &msg, uap->flags);
410}
411
412sendit(s, mp, flags)
413 int s;
414 register struct msghdr *mp;
415 int flags;
416{
417 register struct file *fp;
418 struct uio auio;
419 register struct iovec *iov;
420 register int i;
6d47a3da 421 struct mbuf *to, *rights, *control;
88a7a62a
SL
422 int len;
423
424 fp = getsock(s);
425 if (fp == 0)
426 return;
427 auio.uio_iov = mp->msg_iov;
428 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 429 auio.uio_segflg = UIO_USERSPACE;
c4ec2128 430 auio.uio_rw = UIO_WRITE;
88a7a62a
SL
431 auio.uio_offset = 0; /* XXX */
432 auio.uio_resid = 0;
433 iov = mp->msg_iov;
125c8f95 434 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
435 if (iov->iov_len < 0) {
436 u.u_error = EINVAL;
437 return;
438 }
0f6422b0
MK
439 if (iov->iov_len == 0)
440 continue;
88a7a62a
SL
441 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
442 u.u_error = EFAULT;
443 return;
444 }
445 auio.uio_resid += iov->iov_len;
88a7a62a
SL
446 }
447 if (mp->msg_name) {
448 u.u_error =
98447d3f 449 sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
88a7a62a
SL
450 if (u.u_error)
451 return;
452 } else
453 to = 0;
454 if (mp->msg_accrights) {
455 u.u_error =
98447d3f
MK
456 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
457 MT_RIGHTS);
88a7a62a
SL
458 if (u.u_error)
459 goto bad;
460 } else
461 rights = 0;
6d47a3da
MK
462 if (mp->msg_control) {
463 u.u_error =
464 sockargs(&control, mp->msg_control, mp->msg_controllen,
465 MT_CONTROL);
466 if (u.u_error)
467 goto bad;
468 } else
469 control = 0;
88a7a62a 470 len = auio.uio_resid;
6d47a3da
MK
471 if (setjmp(&u.u_qsave)) { /* XXX */
472 if (auio.uio_resid == len) {
473 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
474 u.u_error = EINTR;
475 else
476 u.u_eosys = RESTARTSYS;
477 }
478 } else
479 u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
480 flags, rights, control);
88a7a62a 481 u.u_r.r_val1 = len - auio.uio_resid;
6d47a3da 482bad:
88a7a62a
SL
483 if (rights)
484 m_freem(rights);
88a7a62a
SL
485 if (to)
486 m_freem(to);
6d47a3da
MK
487 if (control)
488 m_freem(control);
cf012934
BJ
489}
490
f4d2893a
MK
491#ifdef COMPAT_43
492recvfrom()
493{
494 recvfrom1(0);
495}
496
497orecvfrom()
498{
499 recvfrom1(1);
500}
501
502recvfrom1(compat_43)
503{ /* vi will want an extra } to be happy! */
504#else
cf012934
BJ
505recvfrom()
506{
f4d2893a
MK
507 int compat_43 = 0;
508#endif
cf012934
BJ
509 register struct a {
510 int s;
511 caddr_t buf;
512 int len;
513 int flags;
514 caddr_t from;
515 int *fromlenaddr;
516 } *uap = (struct a *)u.u_ap;
88a7a62a 517 struct msghdr msg;
cf012934 518 struct iovec aiov;
88a7a62a 519 int len;
cf012934 520
6d47a3da
MK
521 if (uap->fromlenaddr) {
522 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
523 sizeof (len));
524 if (u.u_error)
525 return;
526 } else
527 len = 0;
88a7a62a
SL
528 msg.msg_name = uap->from;
529 msg.msg_namelen = len;
530 msg.msg_iov = &aiov;
531 msg.msg_iovlen = 1;
cf012934
BJ
532 aiov.iov_base = uap->buf;
533 aiov.iov_len = uap->len;
88a7a62a 534 msg.msg_accrights = 0;
6d47a3da
MK
535 msg.msg_control = 0;
536 msg.msg_flags = uap->flags;
a2aebb63 537 recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, compat_43);
cf012934 538}
6d47a3da 539#ifdef COMPAT_43
6d47a3da 540orecv()
cf012934
BJ
541{
542 register struct a {
543 int s;
544 caddr_t buf;
545 int len;
546 int flags;
547 } *uap = (struct a *)u.u_ap;
88a7a62a 548 struct msghdr msg;
cf012934
BJ
549 struct iovec aiov;
550
88a7a62a
SL
551 msg.msg_name = 0;
552 msg.msg_namelen = 0;
553 msg.msg_iov = &aiov;
554 msg.msg_iovlen = 1;
cf012934
BJ
555 aiov.iov_base = uap->buf;
556 aiov.iov_len = uap->len;
88a7a62a 557 msg.msg_accrights = 0;
6d47a3da
MK
558 msg.msg_control = 0;
559 msg.msg_flags = uap->flags;
a2aebb63 560 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
6d47a3da
MK
561}
562
563orecvmsg()
564{
565 register struct a {
566 int s;
567 struct omsghdr *msg;
568 int flags;
569 } *uap = (struct a *)u.u_ap;
570 struct msghdr msg;
571 struct iovec aiov[MSG_MAXIOVLEN];
572
573 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
574 sizeof (struct omsghdr));
575 if (u.u_error)
576 return;
577 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
578 u.u_error = EMSGSIZE;
579 return;
580 }
581 msg.msg_control = 0;
582 msg.msg_flags = uap->flags;
583 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
584 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
585 if (u.u_error)
586 return;
587 msg.msg_iov = aiov;
588 if (msg.msg_accrights)
589 if (useracc((caddr_t)msg.msg_accrights,
590 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
591 u.u_error = EFAULT;
592 return;
593 }
594
595 recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
a2aebb63 596 (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1);
cf012934 597}
6d47a3da 598#endif
cf012934 599
88a7a62a 600recvmsg()
cf012934 601{
88a7a62a
SL
602 register struct a {
603 int s;
604 struct msghdr *msg;
605 int flags;
606 } *uap = (struct a *)u.u_ap;
607 struct msghdr msg;
f4d2893a 608 struct iovec aiov[MSG_MAXIOVLEN], *uiov;
cf012934 609
88a7a62a
SL
610 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
611 if (u.u_error)
612 return;
613 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
614 u.u_error = EMSGSIZE;
615 return;
616 }
6d47a3da
MK
617 msg.msg_flags = uap->flags;
618 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a
SL
619 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
620 if (u.u_error)
621 return;
f4d2893a 622 uiov = msg.msg_iov;
88a7a62a
SL
623 msg.msg_iov = aiov;
624 if (msg.msg_accrights)
625 if (useracc((caddr_t)msg.msg_accrights,
626 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
627 u.u_error = EFAULT;
628 return;
629 }
6d47a3da
MK
630 if (msg.msg_control)
631 if (useracc((caddr_t)msg.msg_control,
632 (unsigned)msg.msg_controllen, B_WRITE) == 0) {
633 u.u_error = EFAULT;
634 return;
635 }
a2aebb63 636 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
f4d2893a
MK
637 msg.msg_iov = uiov;
638 u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
cf012934
BJ
639}
640
c4ec2128 641/* ARGSUSED */
a2aebb63 642recvit(s, mp, namelenp, rightslenp, compat_43)
f4d2893a 643 int s, compat_43;
88a7a62a 644 register struct msghdr *mp;
a2aebb63 645 caddr_t namelenp, rightslenp;
cf012934 646{
88a7a62a
SL
647 register struct file *fp;
648 struct uio auio;
649 register struct iovec *iov;
650 register int i;
88a7a62a 651 int len;
6d47a3da 652 struct mbuf *from = 0, *rights = 0, *control = 0;
88a7a62a
SL
653
654 fp = getsock(s);
655 if (fp == 0)
656 return;
657 auio.uio_iov = mp->msg_iov;
658 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 659 auio.uio_segflg = UIO_USERSPACE;
c4ec2128 660 auio.uio_rw = UIO_READ;
88a7a62a
SL
661 auio.uio_offset = 0; /* XXX */
662 auio.uio_resid = 0;
663 iov = mp->msg_iov;
125c8f95 664 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
665 if (iov->iov_len < 0) {
666 u.u_error = EINVAL;
667 return;
668 }
0f6422b0
MK
669 if (iov->iov_len == 0)
670 continue;
88a7a62a
SL
671 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
672 u.u_error = EFAULT;
673 return;
674 }
675 auio.uio_resid += iov->iov_len;
88a7a62a
SL
676 }
677 len = auio.uio_resid;
6d47a3da
MK
678 if (setjmp(&u.u_qsave)) { /* XXX */
679 if (auio.uio_resid == len) {
680 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
681 u.u_error = EINTR;
682 else
683 u.u_eosys = RESTARTSYS;
684 }
685 } else
686 u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
687 &mp->msg_flags, &rights, &control);
88a7a62a
SL
688 u.u_r.r_val1 = len - auio.uio_resid;
689 if (mp->msg_name) {
690 len = mp->msg_namelen;
691 if (len <= 0 || from == 0)
692 len = 0;
693 else {
f4d2893a
MK
694#ifdef COMPAT_43
695 if (compat_43)
696 mtod(from, struct osockaddr *)->sa_family =
697 mtod(from, struct sockaddr *)->sa_family;
698#endif
699 if (len > from->m_len) /* ??? */
88a7a62a 700 len = from->m_len;
6d47a3da 701 (void) copyout(mtod(from, caddr_t),
88a7a62a
SL
702 (caddr_t)mp->msg_name, (unsigned)len);
703 }
a2aebb63 704 mp->msg_namelen = len;
6d47a3da
MK
705 if (namelenp)
706 (void) copyout((caddr_t)&len, namelenp, sizeof (int));
88a7a62a
SL
707 }
708 if (mp->msg_accrights) {
709 len = mp->msg_accrightslen;
710 if (len <= 0 || rights == 0)
711 len = 0;
712 else {
713 if (len > rights->m_len)
714 len = rights->m_len;
715 (void) copyout((caddr_t)mtod(rights, caddr_t),
716 (caddr_t)mp->msg_accrights, (unsigned)len);
717 }
a2aebb63 718 mp->msg_accrightslen = len;
6d47a3da
MK
719 if (rightslenp)
720 (void) copyout((caddr_t)&len, rightslenp, sizeof (int));
721 }
722 if (mp->msg_control) {
723 len = mp->msg_controllen;
724 if (len <= 0 || control == 0)
725 len = 0;
726 else {
727 if (len >= control->m_len)
728 len = control->m_len;
729 else
730 mp->msg_flags |= MSG_CTRUNC;
731 (void) copyout((caddr_t)mtod(control, caddr_t),
732 (caddr_t)mp->msg_control, (unsigned)len);
733 }
a2aebb63 734 mp->msg_controllen = len;
88a7a62a
SL
735 }
736 if (rights)
737 m_freem(rights);
738 if (from)
739 m_freem(from);
6d47a3da
MK
740 if (control)
741 m_freem(control);
cf012934
BJ
742}
743
744shutdown()
745{
6ef233bf
SL
746 struct a {
747 int s;
748 int how;
749 } *uap = (struct a *)u.u_ap;
750 struct file *fp;
cf012934 751
88a7a62a 752 fp = getsock(uap->s);
6ef233bf
SL
753 if (fp == 0)
754 return;
88a7a62a 755 u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
cf012934
BJ
756}
757
66f52238
SL
758setsockopt()
759{
760 struct a {
761 int s;
762 int level;
763 int name;
764 caddr_t val;
765 int valsize;
766 } *uap = (struct a *)u.u_ap;
767 struct file *fp;
d2cba8de 768 struct mbuf *m = NULL;
66f52238 769
88a7a62a 770 fp = getsock(uap->s);
66f52238
SL
771 if (fp == 0)
772 return;
66f52238
SL
773 if (uap->valsize > MLEN) {
774 u.u_error = EINVAL;
775 return;
776 }
d2cba8de
SL
777 if (uap->val) {
778 m = m_get(M_WAIT, MT_SOOPTS);
7c52d753 779 if (m == NULL) {
d2cba8de
SL
780 u.u_error = ENOBUFS;
781 return;
782 }
88a7a62a
SL
783 u.u_error =
784 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
61ec2127
SL
785 if (u.u_error) {
786 (void) m_free(m);
787 return;
788 }
d2cba8de 789 m->m_len = uap->valsize;
66f52238 790 }
88a7a62a
SL
791 u.u_error =
792 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
66f52238
SL
793}
794
795getsockopt()
796{
797 struct a {
798 int s;
799 int level;
800 int name;
801 caddr_t val;
802 int *avalsize;
803 } *uap = (struct a *)u.u_ap;
804 struct file *fp;
d2cba8de 805 struct mbuf *m = NULL;
66f52238
SL
806 int valsize;
807
88a7a62a 808 fp = getsock(uap->s);
66f52238
SL
809 if (fp == 0)
810 return;
d2cba8de
SL
811 if (uap->val) {
812 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
813 sizeof (valsize));
814 if (u.u_error)
815 return;
61ec2127
SL
816 } else
817 valsize = 0;
88a7a62a 818 u.u_error =
61ec2127 819 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
66f52238
SL
820 if (u.u_error)
821 goto bad;
61ec2127 822 if (uap->val && valsize && m != NULL) {
d2cba8de
SL
823 if (valsize > m->m_len)
824 valsize = m->m_len;
825 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
826 if (u.u_error)
827 goto bad;
828 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
829 sizeof (valsize));
830 }
66f52238 831bad:
d2cba8de
SL
832 if (m != NULL)
833 (void) m_free(m);
66f52238
SL
834}
835
cf012934
BJ
836pipe()
837{
0c9a45f0 838 struct file *rf, *wf;
cf012934 839 struct socket *rso, *wso;
0c9a45f0 840 int fd, r;
cf012934 841
88a7a62a 842 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
2b4b57cd
BJ
843 if (u.u_error)
844 return;
88a7a62a 845 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
cf012934 846 if (u.u_error)
b242cf10 847 goto free1;
0c9a45f0 848 if (u.u_error = falloc(&rf, &fd))
cf012934 849 goto free2;
0c9a45f0 850 u.u_r.r_val1 = fd;
cf012934
BJ
851 rf->f_flag = FREAD;
852 rf->f_type = DTYPE_SOCKET;
88a7a62a
SL
853 rf->f_ops = &socketops;
854 rf->f_data = (caddr_t)rso;
0c9a45f0 855 if (u.u_error = falloc(&wf, &fd))
cf012934
BJ
856 goto free3;
857 wf->f_flag = FWRITE;
858 wf->f_type = DTYPE_SOCKET;
88a7a62a
SL
859 wf->f_ops = &socketops;
860 wf->f_data = (caddr_t)wso;
0c9a45f0 861 u.u_r.r_val2 = fd;
d97afdcc 862 if (u.u_error = unp_connect2(wso, rso))
cf012934 863 goto free4;
9c58d471
MK
864 wso->so_state |= SS_CANTRCVMORE;
865 rso->so_state |= SS_CANTSENDMORE;
cf012934
BJ
866 return;
867free4:
868 wf->f_count = 0;
869 u.u_ofile[u.u_r.r_val2] = 0;
870free3:
871 rf->f_count = 0;
c4ec2128 872 u.u_ofile[u.u_r.r_val1] = 0;
cf012934 873free2:
8011f5df 874 (void)soclose(wso);
b242cf10 875free1:
8011f5df 876 (void)soclose(rso);
cc15ab5d 877}
a3076b07
BJ
878
879/*
70f2eac5 880 * Get socket name.
a3076b07 881 */
f4d2893a
MK
882#ifdef COMPAT_43
883getsockname()
884{
885 getsockname1(0);
886}
887
888ogetsockname()
889{
890 getsockname1(1);
891}
892
893getsockname1(compat_43)
894#else
70f2eac5 895getsockname()
f4d2893a 896#endif
a3076b07
BJ
897{
898 register struct a {
899 int fdes;
70f2eac5
SL
900 caddr_t asa;
901 int *alen;
a3076b07
BJ
902 } *uap = (struct a *)u.u_ap;
903 register struct file *fp;
05d69517 904 register struct socket *so;
cf012934 905 struct mbuf *m;
70f2eac5 906 int len;
a3076b07 907
88a7a62a 908 fp = getsock(uap->fdes);
a3076b07
BJ
909 if (fp == 0)
910 return;
70f2eac5
SL
911 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
912 if (u.u_error)
913 return;
88a7a62a 914 so = (struct socket *)fp->f_data;
cce93e4b 915 m = m_getclr(M_WAIT, MT_SONAME);
7c52d753
SL
916 if (m == NULL) {
917 u.u_error = ENOBUFS;
918 return;
919 }
70f2eac5
SL
920 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
921 if (u.u_error)
922 goto bad;
923 if (len > m->m_len)
924 len = m->m_len;
f4d2893a
MK
925#ifdef COMPAT_43
926 if (compat_43)
927 mtod(m, struct osockaddr *)->sa_family =
928 mtod(m, struct sockaddr *)->sa_family;
929#endif
70f2eac5 930 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
f4d2893a
MK
931 if (u.u_error == 0)
932 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen,
933 sizeof (len));
cf012934
BJ
934bad:
935 m_freem(m);
936}
937
f4d2893a
MK
938/*
939 * Get name of peer for connected socket.
940 */
6d47a3da 941#ifdef COMPAT_43
f4d2893a 942getpeername()
6d47a3da 943{
f4d2893a 944 getpeername1(0);
6d47a3da 945}
6d47a3da 946
f4d2893a
MK
947ogetpeername()
948{
949 getpeername1(1);
950}
951
952getpeername1(compat_43)
953#else
a7343092 954getpeername()
f4d2893a 955#endif
a7343092
SL
956{
957 register struct a {
958 int fdes;
959 caddr_t asa;
960 int *alen;
961 } *uap = (struct a *)u.u_ap;
962 register struct file *fp;
963 register struct socket *so;
964 struct mbuf *m;
965 int len;
966
967 fp = getsock(uap->fdes);
968 if (fp == 0)
969 return;
970 so = (struct socket *)fp->f_data;
971 if ((so->so_state & SS_ISCONNECTED) == 0) {
972 u.u_error = ENOTCONN;
973 return;
974 }
975 m = m_getclr(M_WAIT, MT_SONAME);
976 if (m == NULL) {
977 u.u_error = ENOBUFS;
978 return;
979 }
980 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
981 if (u.u_error)
982 return;
983 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
984 if (u.u_error)
985 goto bad;
986 if (len > m->m_len)
987 len = m->m_len;
f4d2893a
MK
988#ifdef COMPAT_43
989 if (compat_43)
990 mtod(m, struct osockaddr *)->sa_family =
991 mtod(m, struct sockaddr *)->sa_family;
992#endif
a7343092
SL
993 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
994 if (u.u_error)
995 goto bad;
996 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
997bad:
998 m_freem(m);
999}
1000
98447d3f 1001sockargs(aname, name, namelen, type)
cf012934
BJ
1002 struct mbuf **aname;
1003 caddr_t name;
98447d3f 1004 int namelen, type;
cf012934
BJ
1005{
1006 register struct mbuf *m;
127f7d76 1007 int error;
cf012934 1008
7e4a3868 1009 if ((u_int)namelen > MLEN)
cf012934 1010 return (EINVAL);
98447d3f 1011 m = m_get(M_WAIT, type);
7c52d753
SL
1012 if (m == NULL)
1013 return (ENOBUFS);
cf012934 1014 m->m_len = namelen;
127f7d76
SL
1015 error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
1016 if (error)
cf012934 1017 (void) m_free(m);
127f7d76
SL
1018 else
1019 *aname = m;
a2aebb63
KS
1020 if (type == MT_SONAME) {
1021 register struct sockaddr *sa = mtod(m, struct sockaddr *);
f4d2893a 1022#if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
a2aebb63
KS
1023 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1024 sa->sa_family = sa->sa_len;
f4d2893a 1025#endif
a2aebb63
KS
1026 sa->sa_len = namelen;
1027 }
127f7d76 1028 return (error);
cf012934 1029}
88a7a62a
SL
1030
1031struct file *
1032getsock(fdes)
1033 int fdes;
1034{
1035 register struct file *fp;
1036
c4ec2128
KM
1037 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) {
1038 u.u_error = EBADF;
88a7a62a 1039 return (0);
c4ec2128 1040 }
88a7a62a
SL
1041 if (fp->f_type != DTYPE_SOCKET) {
1042 u.u_error = ENOTSOCK;
1043 return (0);
1044 }
1045 return (fp);
1046}